working together with FATFileSystem
Fork of TinyJpgDec by
TinyJpgDec.cpp@1:79e97662234d, 2015-11-14 (annotated)
- Committer:
- the_sz
- Date:
- Sat Nov 14 02:43:21 2015 +0000
- Revision:
- 1:79e97662234d
- Parent:
- 0:b6f284347a66
INT -> JPEG_INT
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
humlet | 0:b6f284347a66 | 1 | // see also http://elm-chan.org/fsw/tjpgd/00index.html |
humlet | 0:b6f284347a66 | 2 | |
humlet | 0:b6f284347a66 | 3 | /*----------------------------------------------------------------------------/ |
humlet | 0:b6f284347a66 | 4 | / TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 |
humlet | 0:b6f284347a66 | 5 | /-----------------------------------------------------------------------------/ |
humlet | 0:b6f284347a66 | 6 | / The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. |
humlet | 0:b6f284347a66 | 7 | / This is a free software that opened for education, research and commercial |
humlet | 0:b6f284347a66 | 8 | / developments under license policy of following terms. |
humlet | 0:b6f284347a66 | 9 | / |
humlet | 0:b6f284347a66 | 10 | / Copyright (C) 2012, ChaN, all right reserved. |
humlet | 0:b6f284347a66 | 11 | / |
humlet | 0:b6f284347a66 | 12 | / * The TJpgDec module is a free software and there is NO WARRANTY. |
humlet | 0:b6f284347a66 | 13 | / * No restriction on use. You can use, modify and redistribute it for |
humlet | 0:b6f284347a66 | 14 | / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. |
humlet | 0:b6f284347a66 | 15 | / * Redistributions of source code must retain the above copyright notice. |
humlet | 0:b6f284347a66 | 16 | / |
humlet | 0:b6f284347a66 | 17 | /-----------------------------------------------------------------------------/ |
humlet | 0:b6f284347a66 | 18 | / Oct 04,'11 R0.01 First release. |
humlet | 0:b6f284347a66 | 19 | / Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. |
humlet | 0:b6f284347a66 | 20 | / Sep 03,'12 R0.01b Added JD_TBLCLIP option. |
humlet | 0:b6f284347a66 | 21 | /----------------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 22 | |
humlet | 0:b6f284347a66 | 23 | #include "TinyJpgDec.h" |
humlet | 0:b6f284347a66 | 24 | #include "mbed.h" //evillive |
humlet | 0:b6f284347a66 | 25 | |
humlet | 0:b6f284347a66 | 26 | /*-----------------------------------------------*/ |
humlet | 0:b6f284347a66 | 27 | /* Zigzag-order to raster-order conversion table */ |
humlet | 0:b6f284347a66 | 28 | /*-----------------------------------------------*/ |
humlet | 0:b6f284347a66 | 29 | |
humlet | 0:b6f284347a66 | 30 | #define ZIG(n) Zig[n] |
humlet | 0:b6f284347a66 | 31 | |
humlet | 0:b6f284347a66 | 32 | static |
humlet | 0:b6f284347a66 | 33 | const BYTE Zig[64] = { /* Zigzag-order to raster-order conversion table */ |
humlet | 0:b6f284347a66 | 34 | 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, |
humlet | 0:b6f284347a66 | 35 | 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, |
humlet | 0:b6f284347a66 | 36 | 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, |
humlet | 0:b6f284347a66 | 37 | 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 |
humlet | 0:b6f284347a66 | 38 | }; |
humlet | 0:b6f284347a66 | 39 | |
humlet | 0:b6f284347a66 | 40 | |
humlet | 0:b6f284347a66 | 41 | |
humlet | 0:b6f284347a66 | 42 | /*-------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 43 | /* Input scale factor of Arai algorithm */ |
humlet | 0:b6f284347a66 | 44 | /* (scaled up 16 bits for fixed point operations) */ |
humlet | 0:b6f284347a66 | 45 | /*-------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 46 | |
humlet | 0:b6f284347a66 | 47 | #define IPSF(n) Ipsf[n] |
humlet | 0:b6f284347a66 | 48 | |
humlet | 0:b6f284347a66 | 49 | static |
humlet | 0:b6f284347a66 | 50 | const WORD Ipsf[64] = { /* See also aa_idct.png */ |
humlet | 0:b6f284347a66 | 51 | (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), |
humlet | 0:b6f284347a66 | 52 | (WORD)(1.38704*8192), (WORD)(1.92388*8192), (WORD)(1.81226*8192), (WORD)(1.63099*8192), (WORD)(1.38704*8192), (WORD)(1.08979*8192), (WORD)(0.75066*8192), (WORD)(0.38268*8192), |
humlet | 0:b6f284347a66 | 53 | (WORD)(1.30656*8192), (WORD)(1.81226*8192), (WORD)(1.70711*8192), (WORD)(1.53636*8192), (WORD)(1.30656*8192), (WORD)(1.02656*8192), (WORD)(0.70711*8192), (WORD)(0.36048*8192), |
humlet | 0:b6f284347a66 | 54 | (WORD)(1.17588*8192), (WORD)(1.63099*8192), (WORD)(1.53636*8192), (WORD)(1.38268*8192), (WORD)(1.17588*8192), (WORD)(0.92388*8192), (WORD)(0.63638*8192), (WORD)(0.32442*8192), |
humlet | 0:b6f284347a66 | 55 | (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), |
humlet | 0:b6f284347a66 | 56 | (WORD)(0.78570*8192), (WORD)(1.08979*8192), (WORD)(1.02656*8192), (WORD)(0.92388*8192), (WORD)(0.78570*8192), (WORD)(0.61732*8192), (WORD)(0.42522*8192), (WORD)(0.21677*8192), |
humlet | 0:b6f284347a66 | 57 | (WORD)(0.54120*8192), (WORD)(0.75066*8192), (WORD)(0.70711*8192), (WORD)(0.63638*8192), (WORD)(0.54120*8192), (WORD)(0.42522*8192), (WORD)(0.29290*8192), (WORD)(0.14932*8192), |
humlet | 0:b6f284347a66 | 58 | (WORD)(0.27590*8192), (WORD)(0.38268*8192), (WORD)(0.36048*8192), (WORD)(0.32442*8192), (WORD)(0.27590*8192), (WORD)(0.21678*8192), (WORD)(0.14932*8192), (WORD)(0.07612*8192) |
humlet | 0:b6f284347a66 | 59 | }; |
humlet | 0:b6f284347a66 | 60 | |
humlet | 0:b6f284347a66 | 61 | |
humlet | 0:b6f284347a66 | 62 | |
humlet | 0:b6f284347a66 | 63 | /*---------------------------------------------*/ |
humlet | 0:b6f284347a66 | 64 | /* Conversion table for fast clipping process */ |
humlet | 0:b6f284347a66 | 65 | /*---------------------------------------------*/ |
humlet | 0:b6f284347a66 | 66 | |
humlet | 0:b6f284347a66 | 67 | #if JD_TBLCLIP |
humlet | 0:b6f284347a66 | 68 | |
the_sz | 1:79e97662234d | 69 | #define BYTECLIP(v) Clip8[(JPG_UINT)(v) & 0x3FF] |
humlet | 0:b6f284347a66 | 70 | |
humlet | 0:b6f284347a66 | 71 | static |
humlet | 0:b6f284347a66 | 72 | const BYTE Clip8[1024] = { |
humlet | 0:b6f284347a66 | 73 | /* 0..255 */ |
humlet | 0:b6f284347a66 | 74 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, |
humlet | 0:b6f284347a66 | 75 | 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, |
humlet | 0:b6f284347a66 | 76 | 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, |
humlet | 0:b6f284347a66 | 77 | 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, |
humlet | 0:b6f284347a66 | 78 | 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, |
humlet | 0:b6f284347a66 | 79 | 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, |
humlet | 0:b6f284347a66 | 80 | 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, |
humlet | 0:b6f284347a66 | 81 | 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, |
humlet | 0:b6f284347a66 | 82 | /* 256..511 */ |
humlet | 0:b6f284347a66 | 83 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 84 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 85 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 86 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 87 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 88 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 89 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 90 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, |
humlet | 0:b6f284347a66 | 91 | /* -512..-257 */ |
humlet | 0:b6f284347a66 | 92 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 93 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 94 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 95 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 96 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 97 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 98 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 99 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 100 | /* -256..-1 */ |
humlet | 0:b6f284347a66 | 101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 107 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
humlet | 0:b6f284347a66 | 108 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
humlet | 0:b6f284347a66 | 109 | }; |
humlet | 0:b6f284347a66 | 110 | |
humlet | 0:b6f284347a66 | 111 | #else /* JD_TBLCLIP */ |
humlet | 0:b6f284347a66 | 112 | |
humlet | 0:b6f284347a66 | 113 | inline |
humlet | 0:b6f284347a66 | 114 | BYTE BYTECLIP ( |
the_sz | 1:79e97662234d | 115 | JPG_INT val |
humlet | 0:b6f284347a66 | 116 | ) |
humlet | 0:b6f284347a66 | 117 | { |
humlet | 0:b6f284347a66 | 118 | if (val < 0) val = 0; |
humlet | 0:b6f284347a66 | 119 | if (val > 255) val = 255; |
humlet | 0:b6f284347a66 | 120 | |
humlet | 0:b6f284347a66 | 121 | return (BYTE)val; |
humlet | 0:b6f284347a66 | 122 | } |
humlet | 0:b6f284347a66 | 123 | |
humlet | 0:b6f284347a66 | 124 | #endif |
humlet | 0:b6f284347a66 | 125 | |
humlet | 0:b6f284347a66 | 126 | |
humlet | 0:b6f284347a66 | 127 | |
humlet | 0:b6f284347a66 | 128 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 129 | /* Allocate a memory block from memory pool */ |
humlet | 0:b6f284347a66 | 130 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 131 | |
humlet | 0:b6f284347a66 | 132 | static |
humlet | 0:b6f284347a66 | 133 | void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ |
humlet | 0:b6f284347a66 | 134 | JDEC* jd, /* Pointer to the decompressor object */ |
the_sz | 1:79e97662234d | 135 | JPG_UINT nd /* Number of bytes to allocate */ |
humlet | 0:b6f284347a66 | 136 | ) |
humlet | 0:b6f284347a66 | 137 | { |
humlet | 0:b6f284347a66 | 138 | char *rp = 0; |
humlet | 0:b6f284347a66 | 139 | |
humlet | 0:b6f284347a66 | 140 | |
humlet | 0:b6f284347a66 | 141 | nd = (nd + 3) & ~3; /* Align block size to the word boundary */ |
humlet | 0:b6f284347a66 | 142 | |
humlet | 0:b6f284347a66 | 143 | if (jd->sz_pool >= nd) { |
humlet | 0:b6f284347a66 | 144 | jd->sz_pool -= nd; |
humlet | 0:b6f284347a66 | 145 | rp = (char*)jd->pool; /* Get start of available memory pool */ |
humlet | 0:b6f284347a66 | 146 | jd->pool = (void*)(rp + nd); /* Allocate requierd bytes */ |
humlet | 0:b6f284347a66 | 147 | } |
humlet | 0:b6f284347a66 | 148 | |
humlet | 0:b6f284347a66 | 149 | return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ |
humlet | 0:b6f284347a66 | 150 | } |
humlet | 0:b6f284347a66 | 151 | |
humlet | 0:b6f284347a66 | 152 | |
humlet | 0:b6f284347a66 | 153 | |
humlet | 0:b6f284347a66 | 154 | |
humlet | 0:b6f284347a66 | 155 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 156 | /* Create de-quantization and prescaling tables with a DQT segment */ |
humlet | 0:b6f284347a66 | 157 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 158 | |
humlet | 0:b6f284347a66 | 159 | static |
the_sz | 1:79e97662234d | 160 | JRESULT // JPG_UINT evillive |
humlet | 0:b6f284347a66 | 161 | create_qt_tbl ( /* 0:OK, !0:Failed */ |
humlet | 0:b6f284347a66 | 162 | JDEC* jd, /* Pointer to the decompressor object */ |
humlet | 0:b6f284347a66 | 163 | const BYTE* data, /* Pointer to the quantizer tables */ |
the_sz | 1:79e97662234d | 164 | JPG_UINT ndata /* Size of input data */ |
humlet | 0:b6f284347a66 | 165 | ) |
humlet | 0:b6f284347a66 | 166 | { |
the_sz | 1:79e97662234d | 167 | JPG_UINT i; |
humlet | 0:b6f284347a66 | 168 | BYTE d, z; |
humlet | 0:b6f284347a66 | 169 | LONG *pb; |
humlet | 0:b6f284347a66 | 170 | |
humlet | 0:b6f284347a66 | 171 | |
humlet | 0:b6f284347a66 | 172 | while (ndata) { /* Process all tables in the segment */ |
humlet | 0:b6f284347a66 | 173 | if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ |
humlet | 0:b6f284347a66 | 174 | ndata -= 65; |
humlet | 0:b6f284347a66 | 175 | d = *data++; /* Get table property */ |
humlet | 0:b6f284347a66 | 176 | if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ |
humlet | 0:b6f284347a66 | 177 | i = d & 3; /* Get table ID */ |
humlet | 0:b6f284347a66 | 178 | pb = (LONG*)alloc_pool(jd, 64 * sizeof (LONG));/* Allocate a memory block for the table */ |
humlet | 0:b6f284347a66 | 179 | if (!pb) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 180 | jd->qttbl[i] = pb; /* Register the table */ |
humlet | 0:b6f284347a66 | 181 | for (i = 0; i < 64; i++) { /* Load the table */ |
humlet | 0:b6f284347a66 | 182 | z = ZIG(i); /* Zigzag-order to raster-order conversion */ |
humlet | 0:b6f284347a66 | 183 | pb[z] = (LONG)((DWORD)*data++ * IPSF(z)); /* Apply scale factor of Arai algorithm to the de-quantizers */ |
humlet | 0:b6f284347a66 | 184 | } |
humlet | 0:b6f284347a66 | 185 | } |
humlet | 0:b6f284347a66 | 186 | |
humlet | 0:b6f284347a66 | 187 | return JDR_OK; |
humlet | 0:b6f284347a66 | 188 | } |
humlet | 0:b6f284347a66 | 189 | |
humlet | 0:b6f284347a66 | 190 | |
humlet | 0:b6f284347a66 | 191 | |
humlet | 0:b6f284347a66 | 192 | |
humlet | 0:b6f284347a66 | 193 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 194 | /* Create huffman code tables with a DHT segment */ |
humlet | 0:b6f284347a66 | 195 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 196 | |
humlet | 0:b6f284347a66 | 197 | static |
the_sz | 1:79e97662234d | 198 | JRESULT //JPG_UINT evillive |
humlet | 0:b6f284347a66 | 199 | create_huffman_tbl ( /* 0:OK, !0:Failed */ |
humlet | 0:b6f284347a66 | 200 | JDEC* jd, /* Pointer to the decompressor object */ |
humlet | 0:b6f284347a66 | 201 | const BYTE* data, /* Pointer to the packed huffman tables */ |
the_sz | 1:79e97662234d | 202 | JPG_UINT ndata /* Size of input data */ |
humlet | 0:b6f284347a66 | 203 | ) |
humlet | 0:b6f284347a66 | 204 | { |
the_sz | 1:79e97662234d | 205 | JPG_UINT i, j, b, np, cls, num; |
humlet | 0:b6f284347a66 | 206 | BYTE d, *pb, *pd; |
humlet | 0:b6f284347a66 | 207 | WORD hc, *ph; |
humlet | 0:b6f284347a66 | 208 | |
humlet | 0:b6f284347a66 | 209 | |
humlet | 0:b6f284347a66 | 210 | while (ndata) { /* Process all tables in the segment */ |
humlet | 0:b6f284347a66 | 211 | if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ |
humlet | 0:b6f284347a66 | 212 | ndata -= 17; |
humlet | 0:b6f284347a66 | 213 | d = *data++; /* Get table number and class */ |
humlet | 0:b6f284347a66 | 214 | cls = (d >> 4); |
humlet | 0:b6f284347a66 | 215 | num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ |
humlet | 0:b6f284347a66 | 216 | if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ |
humlet | 0:b6f284347a66 | 217 | pb = (BYTE*)alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ |
humlet | 0:b6f284347a66 | 218 | if (!pb) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 219 | jd->huffbits[num][cls] = pb; |
humlet | 0:b6f284347a66 | 220 | for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ |
humlet | 0:b6f284347a66 | 221 | pb[i] = b = *data++; |
humlet | 0:b6f284347a66 | 222 | np += b; /* Get sum of code words for each code */ |
humlet | 0:b6f284347a66 | 223 | } |
humlet | 0:b6f284347a66 | 224 | |
humlet | 0:b6f284347a66 | 225 | ph = (WORD*)alloc_pool(jd, np * sizeof (WORD));/* Allocate a memory block for the code word table */ |
humlet | 0:b6f284347a66 | 226 | if (!ph) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 227 | jd->huffcode[num][cls] = ph; |
humlet | 0:b6f284347a66 | 228 | hc = 0; |
humlet | 0:b6f284347a66 | 229 | for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ |
humlet | 0:b6f284347a66 | 230 | b = pb[i]; |
humlet | 0:b6f284347a66 | 231 | while (b--) ph[j++] = hc++; |
humlet | 0:b6f284347a66 | 232 | hc <<= 1; |
humlet | 0:b6f284347a66 | 233 | } |
humlet | 0:b6f284347a66 | 234 | |
humlet | 0:b6f284347a66 | 235 | if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ |
humlet | 0:b6f284347a66 | 236 | ndata -= np; |
humlet | 0:b6f284347a66 | 237 | pd = (BYTE*)alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ |
humlet | 0:b6f284347a66 | 238 | if (!pd) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 239 | jd->huffdata[num][cls] = pd; |
humlet | 0:b6f284347a66 | 240 | for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code ward */ |
humlet | 0:b6f284347a66 | 241 | d = *data++; |
humlet | 0:b6f284347a66 | 242 | if (!cls && d > 11) return JDR_FMT1; |
humlet | 0:b6f284347a66 | 243 | *pd++ = d; |
humlet | 0:b6f284347a66 | 244 | } |
humlet | 0:b6f284347a66 | 245 | } |
humlet | 0:b6f284347a66 | 246 | |
humlet | 0:b6f284347a66 | 247 | return JDR_OK; |
humlet | 0:b6f284347a66 | 248 | } |
humlet | 0:b6f284347a66 | 249 | |
humlet | 0:b6f284347a66 | 250 | |
humlet | 0:b6f284347a66 | 251 | |
humlet | 0:b6f284347a66 | 252 | |
humlet | 0:b6f284347a66 | 253 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 254 | /* Extract N bits from input stream */ |
humlet | 0:b6f284347a66 | 255 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 256 | |
humlet | 0:b6f284347a66 | 257 | static |
the_sz | 1:79e97662234d | 258 | JPG_INT bitext ( /* >=0: extracted data, <0: error code */ |
humlet | 0:b6f284347a66 | 259 | JDEC* jd, /* Pointer to the decompressor object */ |
the_sz | 1:79e97662234d | 260 | JPG_UINT nbit /* Number of bits to extract (1 to 11) */ |
humlet | 0:b6f284347a66 | 261 | ) |
humlet | 0:b6f284347a66 | 262 | { |
humlet | 0:b6f284347a66 | 263 | BYTE msk, s, *dp; |
the_sz | 1:79e97662234d | 264 | JPG_UINT dc, v, f; |
humlet | 0:b6f284347a66 | 265 | |
humlet | 0:b6f284347a66 | 266 | |
humlet | 0:b6f284347a66 | 267 | msk = jd->dmsk; |
humlet | 0:b6f284347a66 | 268 | dc = jd->dctr; |
humlet | 0:b6f284347a66 | 269 | dp = jd->dptr; /* Bit mask, number of data available, read ptr */ |
humlet | 0:b6f284347a66 | 270 | s = *dp; |
humlet | 0:b6f284347a66 | 271 | v = f = 0; |
humlet | 0:b6f284347a66 | 272 | do { |
humlet | 0:b6f284347a66 | 273 | if (!msk) { /* Next byte? */ |
humlet | 0:b6f284347a66 | 274 | if (!dc) { /* No input data is available, re-fill input buffer */ |
humlet | 0:b6f284347a66 | 275 | dp = jd->inbuf; /* Top of input buffer */ |
humlet | 0:b6f284347a66 | 276 | dc = jd->infunc(jd, dp, JD_SZBUF); |
the_sz | 1:79e97662234d | 277 | if (!dc) return 0 - (JPG_INT)JDR_INP; /* Err: read error or wrong stream termination */ |
humlet | 0:b6f284347a66 | 278 | } else { |
humlet | 0:b6f284347a66 | 279 | dp++; /* Next data ptr */ |
humlet | 0:b6f284347a66 | 280 | } |
humlet | 0:b6f284347a66 | 281 | dc--; /* Decrement number of available bytes */ |
humlet | 0:b6f284347a66 | 282 | if (f) { /* In flag sequence? */ |
humlet | 0:b6f284347a66 | 283 | f = 0; /* Exit flag sequence */ |
the_sz | 1:79e97662234d | 284 | if (*dp != 0) return 0 - (JPG_INT)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ |
humlet | 0:b6f284347a66 | 285 | *dp = s = 0xFF; /* The flag is a data 0xFF */ |
humlet | 0:b6f284347a66 | 286 | } else { |
humlet | 0:b6f284347a66 | 287 | s = *dp; /* Get next data byte */ |
humlet | 0:b6f284347a66 | 288 | if (s == 0xFF) { /* Is start of flag sequence? */ |
humlet | 0:b6f284347a66 | 289 | f = 1; |
humlet | 0:b6f284347a66 | 290 | continue; /* Enter flag sequence */ |
humlet | 0:b6f284347a66 | 291 | } |
humlet | 0:b6f284347a66 | 292 | } |
humlet | 0:b6f284347a66 | 293 | msk = 0x80; /* Read from MSB */ |
humlet | 0:b6f284347a66 | 294 | } |
humlet | 0:b6f284347a66 | 295 | v <<= 1; /* Get a bit */ |
humlet | 0:b6f284347a66 | 296 | if (s & msk) v++; |
humlet | 0:b6f284347a66 | 297 | msk >>= 1; |
humlet | 0:b6f284347a66 | 298 | nbit--; |
humlet | 0:b6f284347a66 | 299 | } while (nbit); |
humlet | 0:b6f284347a66 | 300 | jd->dmsk = msk; |
humlet | 0:b6f284347a66 | 301 | jd->dctr = dc; |
humlet | 0:b6f284347a66 | 302 | jd->dptr = dp; |
humlet | 0:b6f284347a66 | 303 | |
the_sz | 1:79e97662234d | 304 | return (JPG_INT)v; |
humlet | 0:b6f284347a66 | 305 | } |
humlet | 0:b6f284347a66 | 306 | |
humlet | 0:b6f284347a66 | 307 | |
humlet | 0:b6f284347a66 | 308 | |
humlet | 0:b6f284347a66 | 309 | |
humlet | 0:b6f284347a66 | 310 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 311 | /* Extract a huffman decoded data from input stream */ |
humlet | 0:b6f284347a66 | 312 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 313 | |
humlet | 0:b6f284347a66 | 314 | static |
the_sz | 1:79e97662234d | 315 | JPG_INT huffext ( /* >=0: decoded data, <0: error code */ |
humlet | 0:b6f284347a66 | 316 | JDEC* jd, /* Pointer to the decompressor object */ |
humlet | 0:b6f284347a66 | 317 | const BYTE* hbits, /* Pointer to the bit distribution table */ |
humlet | 0:b6f284347a66 | 318 | const WORD* hcode, /* Pointer to the code word table */ |
humlet | 0:b6f284347a66 | 319 | const BYTE* hdata /* Pointer to the data table */ |
humlet | 0:b6f284347a66 | 320 | ) |
humlet | 0:b6f284347a66 | 321 | { |
humlet | 0:b6f284347a66 | 322 | BYTE msk, s, *dp; |
the_sz | 1:79e97662234d | 323 | JPG_UINT dc, v, f, bl, nd; |
humlet | 0:b6f284347a66 | 324 | |
humlet | 0:b6f284347a66 | 325 | |
humlet | 0:b6f284347a66 | 326 | msk = jd->dmsk; |
humlet | 0:b6f284347a66 | 327 | dc = jd->dctr; |
humlet | 0:b6f284347a66 | 328 | dp = jd->dptr; /* Bit mask, number of data available, read ptr */ |
humlet | 0:b6f284347a66 | 329 | s = *dp; |
humlet | 0:b6f284347a66 | 330 | v = f = 0; |
humlet | 0:b6f284347a66 | 331 | bl = 16; /* Max code length */ |
humlet | 0:b6f284347a66 | 332 | do { |
humlet | 0:b6f284347a66 | 333 | if (!msk) { /* Next byte? */ |
humlet | 0:b6f284347a66 | 334 | if (!dc) { /* No input data is available, re-fill input buffer */ |
humlet | 0:b6f284347a66 | 335 | dp = jd->inbuf; /* Top of input buffer */ |
humlet | 0:b6f284347a66 | 336 | dc = jd->infunc(jd, dp, JD_SZBUF); |
the_sz | 1:79e97662234d | 337 | if (!dc) {printf("huffext KO 1\n");return 0 - (JPG_INT)JDR_INP;} /* Err: read error or wrong stream termination */ |
humlet | 0:b6f284347a66 | 338 | } else { |
humlet | 0:b6f284347a66 | 339 | dp++; /* Next data ptr */ |
humlet | 0:b6f284347a66 | 340 | } |
humlet | 0:b6f284347a66 | 341 | dc--; /* Decrement number of available bytes */ |
humlet | 0:b6f284347a66 | 342 | if (f) { /* In flag sequence? */ |
humlet | 0:b6f284347a66 | 343 | f = 0; /* Exit flag sequence */ |
humlet | 0:b6f284347a66 | 344 | if (*dp != 0) |
the_sz | 1:79e97662234d | 345 | {printf("huffext KO 2\n");return 0 - (JPG_INT)JDR_FMT1;} /* Err: unexpected flag is detected (may be collapted data) */ |
humlet | 0:b6f284347a66 | 346 | *dp = s = 0xFF; /* The flag is a data 0xFF */ |
humlet | 0:b6f284347a66 | 347 | } else { |
humlet | 0:b6f284347a66 | 348 | s = *dp; /* Get next data byte */ |
humlet | 0:b6f284347a66 | 349 | if (s == 0xFF) { /* Is start of flag sequence? */ |
humlet | 0:b6f284347a66 | 350 | f = 1; |
humlet | 0:b6f284347a66 | 351 | continue; /* Enter flag sequence, get trailing byte */ |
humlet | 0:b6f284347a66 | 352 | } |
humlet | 0:b6f284347a66 | 353 | } |
humlet | 0:b6f284347a66 | 354 | msk = 0x80; /* Read from MSB */ |
humlet | 0:b6f284347a66 | 355 | } |
humlet | 0:b6f284347a66 | 356 | v <<= 1; /* Get a bit */ |
humlet | 0:b6f284347a66 | 357 | if (s & msk) v++; |
humlet | 0:b6f284347a66 | 358 | msk >>= 1; |
humlet | 0:b6f284347a66 | 359 | |
humlet | 0:b6f284347a66 | 360 | for (nd = *hbits++; nd; nd--) { /* Search the code word in this bit length */ |
humlet | 0:b6f284347a66 | 361 | if (v == *hcode++) { /* Matched? */ |
humlet | 0:b6f284347a66 | 362 | jd->dmsk = msk; |
humlet | 0:b6f284347a66 | 363 | jd->dctr = dc; |
humlet | 0:b6f284347a66 | 364 | jd->dptr = dp; |
humlet | 0:b6f284347a66 | 365 | //printf("huffext OK\n"); |
humlet | 0:b6f284347a66 | 366 | return *hdata; /* Return the decoded data */ |
humlet | 0:b6f284347a66 | 367 | } |
humlet | 0:b6f284347a66 | 368 | hdata++; |
humlet | 0:b6f284347a66 | 369 | } |
humlet | 0:b6f284347a66 | 370 | bl--; |
humlet | 0:b6f284347a66 | 371 | } while (bl); |
humlet | 0:b6f284347a66 | 372 | printf("huffext KO 3\n"); |
the_sz | 1:79e97662234d | 373 | return 0 - (JPG_INT)JDR_FMT1; /* Err: code not found (may be collapted data) */ |
humlet | 0:b6f284347a66 | 374 | } |
humlet | 0:b6f284347a66 | 375 | |
humlet | 0:b6f284347a66 | 376 | |
humlet | 0:b6f284347a66 | 377 | |
humlet | 0:b6f284347a66 | 378 | |
humlet | 0:b6f284347a66 | 379 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 380 | /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ |
humlet | 0:b6f284347a66 | 381 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 382 | |
humlet | 0:b6f284347a66 | 383 | static |
humlet | 0:b6f284347a66 | 384 | void block_idct ( |
humlet | 0:b6f284347a66 | 385 | LONG* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ |
humlet | 0:b6f284347a66 | 386 | BYTE* dst /* Pointer to the destination to store the block as byte array */ |
humlet | 0:b6f284347a66 | 387 | ) |
humlet | 0:b6f284347a66 | 388 | { |
humlet | 0:b6f284347a66 | 389 | const LONG M13 = (LONG)(1.41421*4096), M2 = (LONG)(1.08239*4096), M4 = (LONG)(2.61313*4096), M5 = (LONG)(1.84776*4096); |
humlet | 0:b6f284347a66 | 390 | LONG v0, v1, v2, v3, v4, v5, v6, v7; |
humlet | 0:b6f284347a66 | 391 | LONG t10, t11, t12, t13; |
the_sz | 1:79e97662234d | 392 | JPG_UINT i; |
humlet | 0:b6f284347a66 | 393 | |
humlet | 0:b6f284347a66 | 394 | /* Process columns */ |
humlet | 0:b6f284347a66 | 395 | for (i = 0; i < 8; i++) { |
humlet | 0:b6f284347a66 | 396 | v0 = src[8 * 0]; /* Get even elements */ |
humlet | 0:b6f284347a66 | 397 | v1 = src[8 * 2]; |
humlet | 0:b6f284347a66 | 398 | v2 = src[8 * 4]; |
humlet | 0:b6f284347a66 | 399 | v3 = src[8 * 6]; |
humlet | 0:b6f284347a66 | 400 | |
humlet | 0:b6f284347a66 | 401 | t10 = v0 + v2; /* Process the even elements */ |
humlet | 0:b6f284347a66 | 402 | t12 = v0 - v2; |
humlet | 0:b6f284347a66 | 403 | t11 = (v1 - v3) * M13 >> 12; |
humlet | 0:b6f284347a66 | 404 | v3 += v1; |
humlet | 0:b6f284347a66 | 405 | t11 -= v3; |
humlet | 0:b6f284347a66 | 406 | v0 = t10 + v3; |
humlet | 0:b6f284347a66 | 407 | v3 = t10 - v3; |
humlet | 0:b6f284347a66 | 408 | v1 = t11 + t12; |
humlet | 0:b6f284347a66 | 409 | v2 = t12 - t11; |
humlet | 0:b6f284347a66 | 410 | |
humlet | 0:b6f284347a66 | 411 | v4 = src[8 * 7]; /* Get odd elements */ |
humlet | 0:b6f284347a66 | 412 | v5 = src[8 * 1]; |
humlet | 0:b6f284347a66 | 413 | v6 = src[8 * 5]; |
humlet | 0:b6f284347a66 | 414 | v7 = src[8 * 3]; |
humlet | 0:b6f284347a66 | 415 | |
humlet | 0:b6f284347a66 | 416 | t10 = v5 - v4; /* Process the odd elements */ |
humlet | 0:b6f284347a66 | 417 | t11 = v5 + v4; |
humlet | 0:b6f284347a66 | 418 | t12 = v6 - v7; |
humlet | 0:b6f284347a66 | 419 | v7 += v6; |
humlet | 0:b6f284347a66 | 420 | v5 = (t11 - v7) * M13 >> 12; |
humlet | 0:b6f284347a66 | 421 | v7 += t11; |
humlet | 0:b6f284347a66 | 422 | t13 = (t10 + t12) * M5 >> 12; |
humlet | 0:b6f284347a66 | 423 | v4 = t13 - (t10 * M2 >> 12); |
humlet | 0:b6f284347a66 | 424 | v6 = t13 - (t12 * M4 >> 12) - v7; |
humlet | 0:b6f284347a66 | 425 | v5 -= v6; |
humlet | 0:b6f284347a66 | 426 | v4 -= v5; |
humlet | 0:b6f284347a66 | 427 | |
humlet | 0:b6f284347a66 | 428 | src[8 * 0] = v0 + v7; /* Write-back transformed values */ |
humlet | 0:b6f284347a66 | 429 | src[8 * 7] = v0 - v7; |
humlet | 0:b6f284347a66 | 430 | src[8 * 1] = v1 + v6; |
humlet | 0:b6f284347a66 | 431 | src[8 * 6] = v1 - v6; |
humlet | 0:b6f284347a66 | 432 | src[8 * 2] = v2 + v5; |
humlet | 0:b6f284347a66 | 433 | src[8 * 5] = v2 - v5; |
humlet | 0:b6f284347a66 | 434 | src[8 * 3] = v3 + v4; |
humlet | 0:b6f284347a66 | 435 | src[8 * 4] = v3 - v4; |
humlet | 0:b6f284347a66 | 436 | |
humlet | 0:b6f284347a66 | 437 | src++; /* Next column */ |
humlet | 0:b6f284347a66 | 438 | } |
humlet | 0:b6f284347a66 | 439 | |
humlet | 0:b6f284347a66 | 440 | /* Process rows */ |
humlet | 0:b6f284347a66 | 441 | src -= 8; |
humlet | 0:b6f284347a66 | 442 | for (i = 0; i < 8; i++) { |
humlet | 0:b6f284347a66 | 443 | v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ |
humlet | 0:b6f284347a66 | 444 | v1 = src[2]; |
humlet | 0:b6f284347a66 | 445 | v2 = src[4]; |
humlet | 0:b6f284347a66 | 446 | v3 = src[6]; |
humlet | 0:b6f284347a66 | 447 | |
humlet | 0:b6f284347a66 | 448 | t10 = v0 + v2; /* Process the even elements */ |
humlet | 0:b6f284347a66 | 449 | t12 = v0 - v2; |
humlet | 0:b6f284347a66 | 450 | t11 = (v1 - v3) * M13 >> 12; |
humlet | 0:b6f284347a66 | 451 | v3 += v1; |
humlet | 0:b6f284347a66 | 452 | t11 -= v3; |
humlet | 0:b6f284347a66 | 453 | v0 = t10 + v3; |
humlet | 0:b6f284347a66 | 454 | v3 = t10 - v3; |
humlet | 0:b6f284347a66 | 455 | v1 = t11 + t12; |
humlet | 0:b6f284347a66 | 456 | v2 = t12 - t11; |
humlet | 0:b6f284347a66 | 457 | |
humlet | 0:b6f284347a66 | 458 | v4 = src[7]; /* Get odd elements */ |
humlet | 0:b6f284347a66 | 459 | v5 = src[1]; |
humlet | 0:b6f284347a66 | 460 | v6 = src[5]; |
humlet | 0:b6f284347a66 | 461 | v7 = src[3]; |
humlet | 0:b6f284347a66 | 462 | |
humlet | 0:b6f284347a66 | 463 | t10 = v5 - v4; /* Process the odd elements */ |
humlet | 0:b6f284347a66 | 464 | t11 = v5 + v4; |
humlet | 0:b6f284347a66 | 465 | t12 = v6 - v7; |
humlet | 0:b6f284347a66 | 466 | v7 += v6; |
humlet | 0:b6f284347a66 | 467 | v5 = (t11 - v7) * M13 >> 12; |
humlet | 0:b6f284347a66 | 468 | v7 += t11; |
humlet | 0:b6f284347a66 | 469 | t13 = (t10 + t12) * M5 >> 12; |
humlet | 0:b6f284347a66 | 470 | v4 = t13 - (t10 * M2 >> 12); |
humlet | 0:b6f284347a66 | 471 | v6 = t13 - (t12 * M4 >> 12) - v7; |
humlet | 0:b6f284347a66 | 472 | v5 -= v6; |
humlet | 0:b6f284347a66 | 473 | v4 -= v5; |
humlet | 0:b6f284347a66 | 474 | |
humlet | 0:b6f284347a66 | 475 | dst[0] = BYTECLIP((v0 + v7) >> 8); /* Descale the transformed values 8 bits and output */ |
humlet | 0:b6f284347a66 | 476 | dst[7] = BYTECLIP((v0 - v7) >> 8); |
humlet | 0:b6f284347a66 | 477 | dst[1] = BYTECLIP((v1 + v6) >> 8); |
humlet | 0:b6f284347a66 | 478 | dst[6] = BYTECLIP((v1 - v6) >> 8); |
humlet | 0:b6f284347a66 | 479 | dst[2] = BYTECLIP((v2 + v5) >> 8); |
humlet | 0:b6f284347a66 | 480 | dst[5] = BYTECLIP((v2 - v5) >> 8); |
humlet | 0:b6f284347a66 | 481 | dst[3] = BYTECLIP((v3 + v4) >> 8); |
humlet | 0:b6f284347a66 | 482 | dst[4] = BYTECLIP((v3 - v4) >> 8); |
humlet | 0:b6f284347a66 | 483 | dst += 8; |
humlet | 0:b6f284347a66 | 484 | |
humlet | 0:b6f284347a66 | 485 | src += 8; /* Next row */ |
humlet | 0:b6f284347a66 | 486 | } |
humlet | 0:b6f284347a66 | 487 | } |
humlet | 0:b6f284347a66 | 488 | |
humlet | 0:b6f284347a66 | 489 | |
humlet | 0:b6f284347a66 | 490 | |
humlet | 0:b6f284347a66 | 491 | |
humlet | 0:b6f284347a66 | 492 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 493 | /* Load all blocks in the MCU into working buffer */ |
humlet | 0:b6f284347a66 | 494 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 495 | |
humlet | 0:b6f284347a66 | 496 | static |
humlet | 0:b6f284347a66 | 497 | JRESULT |
the_sz | 1:79e97662234d | 498 | //JPG_INT evillive |
humlet | 0:b6f284347a66 | 499 | mcu_load ( |
humlet | 0:b6f284347a66 | 500 | JDEC* jd /* Pointer to the decompressor object */ |
humlet | 0:b6f284347a66 | 501 | ) |
humlet | 0:b6f284347a66 | 502 | { |
humlet | 0:b6f284347a66 | 503 | LONG *tmp = (LONG*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ |
the_sz | 1:79e97662234d | 504 | JPG_UINT blk, nby, nbc, i, z, id, cmp; |
the_sz | 1:79e97662234d | 505 | JPG_INT b, d, e; |
humlet | 0:b6f284347a66 | 506 | BYTE *bp; |
humlet | 0:b6f284347a66 | 507 | const BYTE *hb, *hd; |
humlet | 0:b6f284347a66 | 508 | const WORD *hc; |
humlet | 0:b6f284347a66 | 509 | const LONG *dqf; |
humlet | 0:b6f284347a66 | 510 | |
humlet | 0:b6f284347a66 | 511 | |
humlet | 0:b6f284347a66 | 512 | nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ |
humlet | 0:b6f284347a66 | 513 | nbc = 2; /* Number of C blocks (2) */ |
humlet | 0:b6f284347a66 | 514 | bp = jd->mcubuf; /* Pointer to the first block */ |
humlet | 0:b6f284347a66 | 515 | |
humlet | 0:b6f284347a66 | 516 | for (blk = 0; blk < nby + nbc; blk++) { |
humlet | 0:b6f284347a66 | 517 | cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ |
humlet | 0:b6f284347a66 | 518 | id = cmp ? 1 : 0; /* Huffman table ID of the component */ |
humlet | 0:b6f284347a66 | 519 | |
humlet | 0:b6f284347a66 | 520 | /* Extract a DC element from input stream */ |
humlet | 0:b6f284347a66 | 521 | hb = jd->huffbits[id][0]; /* Huffman table for the DC element */ |
humlet | 0:b6f284347a66 | 522 | hc = jd->huffcode[id][0]; |
humlet | 0:b6f284347a66 | 523 | hd = jd->huffdata[id][0]; |
humlet | 0:b6f284347a66 | 524 | b = huffext(jd, hb, hc, hd); /* Extract a huffman coded data (bit length) */ |
humlet | 0:b6f284347a66 | 525 | //if (b < 0) return 0 - b; /* Err: invalid code or input */ |
humlet | 0:b6f284347a66 | 526 | if (b < 0) {printf("mcu_load KO 1\n");return (JRESULT)(-b);} // evillive /* Err: invalid code or input */ |
humlet | 0:b6f284347a66 | 527 | d = jd->dcv[cmp]; /* DC value of previous block */ |
humlet | 0:b6f284347a66 | 528 | if (b) { /* If there is any difference from previous block */ |
humlet | 0:b6f284347a66 | 529 | e = bitext(jd, b); /* Extract data bits */ |
humlet | 0:b6f284347a66 | 530 | //if (e < 0) return 0 - e; /* Err: input */ |
humlet | 0:b6f284347a66 | 531 | if (e < 0) {printf("mcu_load KO 2\n");return (JRESULT)(-e); }//evillive |
humlet | 0:b6f284347a66 | 532 | b = 1 << (b - 1); /* MSB position */ |
humlet | 0:b6f284347a66 | 533 | if (!(e & b)) e -= (b << 1) - 1; /* Restore sign if needed */ |
humlet | 0:b6f284347a66 | 534 | d += e; /* Get current value */ |
humlet | 0:b6f284347a66 | 535 | jd->dcv[cmp] = (SHORT)d; /* Save current DC value for next block */ |
humlet | 0:b6f284347a66 | 536 | } |
humlet | 0:b6f284347a66 | 537 | dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ |
humlet | 0:b6f284347a66 | 538 | tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ |
humlet | 0:b6f284347a66 | 539 | |
humlet | 0:b6f284347a66 | 540 | /* Extract following 63 AC elements from input stream */ |
humlet | 0:b6f284347a66 | 541 | for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ |
humlet | 0:b6f284347a66 | 542 | hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ |
humlet | 0:b6f284347a66 | 543 | hc = jd->huffcode[id][1]; |
humlet | 0:b6f284347a66 | 544 | hd = jd->huffdata[id][1]; |
humlet | 0:b6f284347a66 | 545 | i = 1; /* Top of the AC elements */ |
humlet | 0:b6f284347a66 | 546 | do { |
humlet | 0:b6f284347a66 | 547 | b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ |
humlet | 0:b6f284347a66 | 548 | if (b == 0) break; /* EOB? */ |
humlet | 0:b6f284347a66 | 549 | //if (b < 0) return 0 - b; /* Err: invalid code or input error */ |
humlet | 0:b6f284347a66 | 550 | if (b < 0) {printf("mcu_load KO 3\n");return (JRESULT)(-b);}//evillive |
the_sz | 1:79e97662234d | 551 | z = (JPG_UINT)b >> 4; /* Number of leading zero elements */ |
humlet | 0:b6f284347a66 | 552 | if (z) { |
humlet | 0:b6f284347a66 | 553 | i += z; /* Skip zero elements */ |
humlet | 0:b6f284347a66 | 554 | if (i >= 64) {printf("mcu_load KO 4\n");return JDR_FMT1;} /* Too long zero run */ |
humlet | 0:b6f284347a66 | 555 | } |
humlet | 0:b6f284347a66 | 556 | if (b &= 0x0F) { /* Bit length */ |
humlet | 0:b6f284347a66 | 557 | d = bitext(jd, b); /* Extract data bits */ |
humlet | 0:b6f284347a66 | 558 | //if (d < 0) return 0 - d; /* Err: input device */ |
humlet | 0:b6f284347a66 | 559 | if (d < 0) {printf("mcu_load KO 5\n");return (JRESULT)(-d); }// evillive |
humlet | 0:b6f284347a66 | 560 | b = 1 << (b - 1); /* MSB position */ |
humlet | 0:b6f284347a66 | 561 | if (!(d & b)) d -= (b << 1) - 1;/* Restore negative value if needed */ |
humlet | 0:b6f284347a66 | 562 | z = ZIG(i); /* Zigzag-order to raster-order converted index */ |
humlet | 0:b6f284347a66 | 563 | tmp[z] = d * dqf[z] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ |
humlet | 0:b6f284347a66 | 564 | } |
humlet | 0:b6f284347a66 | 565 | } while (++i < 64); /* Next AC element */ |
humlet | 0:b6f284347a66 | 566 | |
humlet | 0:b6f284347a66 | 567 | if (JD_USE_SCALE && jd->scale == 3) |
humlet | 0:b6f284347a66 | 568 | *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ |
humlet | 0:b6f284347a66 | 569 | else |
humlet | 0:b6f284347a66 | 570 | block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ |
humlet | 0:b6f284347a66 | 571 | |
humlet | 0:b6f284347a66 | 572 | bp += 64; /* Next block */ |
humlet | 0:b6f284347a66 | 573 | } |
humlet | 0:b6f284347a66 | 574 | |
humlet | 0:b6f284347a66 | 575 | return JDR_OK; /* All blocks have been loaded successfully */ |
humlet | 0:b6f284347a66 | 576 | } |
humlet | 0:b6f284347a66 | 577 | |
humlet | 0:b6f284347a66 | 578 | |
humlet | 0:b6f284347a66 | 579 | |
humlet | 0:b6f284347a66 | 580 | |
humlet | 0:b6f284347a66 | 581 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 582 | /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ |
humlet | 0:b6f284347a66 | 583 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 584 | |
humlet | 0:b6f284347a66 | 585 | static |
humlet | 0:b6f284347a66 | 586 | JRESULT mcu_output ( |
humlet | 0:b6f284347a66 | 587 | JDEC* jd, /* Pointer to the decompressor object */ |
the_sz | 1:79e97662234d | 588 | JPG_UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ |
the_sz | 1:79e97662234d | 589 | JPG_UINT x, /* MCU position in the image (left of the MCU) */ |
the_sz | 1:79e97662234d | 590 | JPG_UINT y /* MCU position in the image (top of the MCU) */ |
humlet | 0:b6f284347a66 | 591 | ) |
humlet | 0:b6f284347a66 | 592 | { |
the_sz | 1:79e97662234d | 593 | const JPG_INT CVACC = (sizeof (JPG_INT) > 2) ? 1024 : 128; |
the_sz | 1:79e97662234d | 594 | JPG_UINT ix, iy, mx, my, rx, ry; |
the_sz | 1:79e97662234d | 595 | JPG_INT yy, cb, cr; |
humlet | 0:b6f284347a66 | 596 | BYTE *py, *pc, *rgb24; |
humlet | 0:b6f284347a66 | 597 | JRECT rect; |
humlet | 0:b6f284347a66 | 598 | |
humlet | 0:b6f284347a66 | 599 | |
humlet | 0:b6f284347a66 | 600 | mx = jd->msx * 8; |
humlet | 0:b6f284347a66 | 601 | my = jd->msy * 8; /* MCU size (pixel) */ |
humlet | 0:b6f284347a66 | 602 | rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end) */ |
humlet | 0:b6f284347a66 | 603 | ry = (y + my <= jd->height) ? my : jd->height - y; |
humlet | 0:b6f284347a66 | 604 | if (JD_USE_SCALE) { |
humlet | 0:b6f284347a66 | 605 | rx >>= jd->scale; |
humlet | 0:b6f284347a66 | 606 | ry >>= jd->scale; |
humlet | 0:b6f284347a66 | 607 | if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ |
humlet | 0:b6f284347a66 | 608 | x >>= jd->scale; |
humlet | 0:b6f284347a66 | 609 | y >>= jd->scale; |
humlet | 0:b6f284347a66 | 610 | } |
humlet | 0:b6f284347a66 | 611 | rect.left = x; |
humlet | 0:b6f284347a66 | 612 | rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ |
humlet | 0:b6f284347a66 | 613 | rect.top = y; |
humlet | 0:b6f284347a66 | 614 | rect.bottom = y + ry - 1; |
humlet | 0:b6f284347a66 | 615 | |
humlet | 0:b6f284347a66 | 616 | |
humlet | 0:b6f284347a66 | 617 | if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ |
humlet | 0:b6f284347a66 | 618 | |
humlet | 0:b6f284347a66 | 619 | /* Build an RGB MCU from discrete comopnents */ |
humlet | 0:b6f284347a66 | 620 | rgb24 = (BYTE*)jd->workbuf; |
humlet | 0:b6f284347a66 | 621 | for (iy = 0; iy < my; iy++) { |
humlet | 0:b6f284347a66 | 622 | pc = jd->mcubuf; |
humlet | 0:b6f284347a66 | 623 | py = pc + iy * 8; |
humlet | 0:b6f284347a66 | 624 | if (my == 16) { /* Double block height? */ |
humlet | 0:b6f284347a66 | 625 | pc += 64 * 4 + (iy >> 1) * 8; |
humlet | 0:b6f284347a66 | 626 | if (iy >= 8) py += 64; |
humlet | 0:b6f284347a66 | 627 | } else { /* Single block height */ |
humlet | 0:b6f284347a66 | 628 | pc += mx * 8 + iy * 8; |
humlet | 0:b6f284347a66 | 629 | } |
humlet | 0:b6f284347a66 | 630 | for (ix = 0; ix < mx; ix++) { |
humlet | 0:b6f284347a66 | 631 | cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ |
humlet | 0:b6f284347a66 | 632 | cr = pc[64] - 128; |
humlet | 0:b6f284347a66 | 633 | if (mx == 16) { /* Double block width? */ |
humlet | 0:b6f284347a66 | 634 | if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ |
humlet | 0:b6f284347a66 | 635 | pc += ix & 1; /* Increase chroma pointer every two pixels */ |
humlet | 0:b6f284347a66 | 636 | } else { /* Single block width */ |
humlet | 0:b6f284347a66 | 637 | pc++; /* Increase chroma pointer every pixel */ |
humlet | 0:b6f284347a66 | 638 | } |
humlet | 0:b6f284347a66 | 639 | yy = *py++; /* Get Y component */ |
humlet | 0:b6f284347a66 | 640 | |
humlet | 0:b6f284347a66 | 641 | /* Convert YCbCr to RGB */ |
the_sz | 1:79e97662234d | 642 | *rgb24++ = /* R */ BYTECLIP(yy + ((JPG_INT)(1.402 * CVACC) * cr) / CVACC); |
the_sz | 1:79e97662234d | 643 | *rgb24++ = /* G */ BYTECLIP(yy - ((JPG_INT)(0.344 * CVACC) * cb + (JPG_INT)(0.714 * CVACC) * cr) / CVACC); |
the_sz | 1:79e97662234d | 644 | *rgb24++ = /* B */ BYTECLIP(yy + ((JPG_INT)(1.772 * CVACC) * cb) / CVACC); |
humlet | 0:b6f284347a66 | 645 | } |
humlet | 0:b6f284347a66 | 646 | } |
humlet | 0:b6f284347a66 | 647 | |
humlet | 0:b6f284347a66 | 648 | /* Descale the MCU rectangular if needed */ |
humlet | 0:b6f284347a66 | 649 | if (JD_USE_SCALE && jd->scale) { |
the_sz | 1:79e97662234d | 650 | JPG_UINT x, y, r, g, b, s, w, a; |
humlet | 0:b6f284347a66 | 651 | BYTE *op; |
humlet | 0:b6f284347a66 | 652 | |
humlet | 0:b6f284347a66 | 653 | /* Get averaged RGB value of each square correcponds to a pixel */ |
humlet | 0:b6f284347a66 | 654 | s = jd->scale * 2; /* Bumber of shifts for averaging */ |
humlet | 0:b6f284347a66 | 655 | w = 1 << jd->scale; /* Width of square */ |
humlet | 0:b6f284347a66 | 656 | a = (mx - w) * 3; /* Bytes to skip for next line in the square */ |
humlet | 0:b6f284347a66 | 657 | op = (BYTE*)jd->workbuf; |
humlet | 0:b6f284347a66 | 658 | for (iy = 0; iy < my; iy += w) { |
humlet | 0:b6f284347a66 | 659 | for (ix = 0; ix < mx; ix += w) { |
humlet | 0:b6f284347a66 | 660 | rgb24 = (BYTE*)jd->workbuf + (iy * mx + ix) * 3; |
humlet | 0:b6f284347a66 | 661 | r = g = b = 0; |
humlet | 0:b6f284347a66 | 662 | for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ |
humlet | 0:b6f284347a66 | 663 | for (x = 0; x < w; x++) { |
humlet | 0:b6f284347a66 | 664 | r += *rgb24++; |
humlet | 0:b6f284347a66 | 665 | g += *rgb24++; |
humlet | 0:b6f284347a66 | 666 | b += *rgb24++; |
humlet | 0:b6f284347a66 | 667 | } |
humlet | 0:b6f284347a66 | 668 | rgb24 += a; |
humlet | 0:b6f284347a66 | 669 | } /* Put the averaged RGB value as a pixel */ |
humlet | 0:b6f284347a66 | 670 | *op++ = (BYTE)(r >> s); |
humlet | 0:b6f284347a66 | 671 | *op++ = (BYTE)(g >> s); |
humlet | 0:b6f284347a66 | 672 | *op++ = (BYTE)(b >> s); |
humlet | 0:b6f284347a66 | 673 | } |
humlet | 0:b6f284347a66 | 674 | } |
humlet | 0:b6f284347a66 | 675 | } |
humlet | 0:b6f284347a66 | 676 | |
humlet | 0:b6f284347a66 | 677 | } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ |
humlet | 0:b6f284347a66 | 678 | |
humlet | 0:b6f284347a66 | 679 | /* Build a 1/8 descaled RGB MCU from discrete comopnents */ |
humlet | 0:b6f284347a66 | 680 | rgb24 = (BYTE*)jd->workbuf; |
humlet | 0:b6f284347a66 | 681 | pc = jd->mcubuf + mx * my; |
humlet | 0:b6f284347a66 | 682 | cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ |
humlet | 0:b6f284347a66 | 683 | cr = pc[64] - 128; |
humlet | 0:b6f284347a66 | 684 | for (iy = 0; iy < my; iy += 8) { |
humlet | 0:b6f284347a66 | 685 | py = jd->mcubuf; |
humlet | 0:b6f284347a66 | 686 | if (iy == 8) py += 64 * 2; |
humlet | 0:b6f284347a66 | 687 | for (ix = 0; ix < mx; ix += 8) { |
humlet | 0:b6f284347a66 | 688 | yy = *py; /* Get Y component */ |
humlet | 0:b6f284347a66 | 689 | py += 64; |
humlet | 0:b6f284347a66 | 690 | |
humlet | 0:b6f284347a66 | 691 | /* Convert YCbCr to RGB */ |
the_sz | 1:79e97662234d | 692 | *rgb24++ = /* R */ BYTECLIP(yy + ((JPG_INT)(1.402 * CVACC) * cr / CVACC)); |
the_sz | 1:79e97662234d | 693 | *rgb24++ = /* G */ BYTECLIP(yy - ((JPG_INT)(0.344 * CVACC) * cb + (JPG_INT)(0.714 * CVACC) * cr) / CVACC); |
the_sz | 1:79e97662234d | 694 | *rgb24++ = /* B */ BYTECLIP(yy + ((JPG_INT)(1.772 * CVACC) * cb / CVACC)); |
humlet | 0:b6f284347a66 | 695 | } |
humlet | 0:b6f284347a66 | 696 | } |
humlet | 0:b6f284347a66 | 697 | } |
humlet | 0:b6f284347a66 | 698 | |
humlet | 0:b6f284347a66 | 699 | /* Squeeze up pixel table if a part of MCU is to be truncated */ |
humlet | 0:b6f284347a66 | 700 | mx >>= jd->scale; |
humlet | 0:b6f284347a66 | 701 | if (rx < mx) { |
humlet | 0:b6f284347a66 | 702 | BYTE *s, *d; |
the_sz | 1:79e97662234d | 703 | JPG_UINT x, y; |
humlet | 0:b6f284347a66 | 704 | |
humlet | 0:b6f284347a66 | 705 | s = d = (BYTE*)jd->workbuf; |
humlet | 0:b6f284347a66 | 706 | for (y = 0; y < ry; y++) { |
humlet | 0:b6f284347a66 | 707 | for (x = 0; x < rx; x++) { /* Copy effective pixels */ |
humlet | 0:b6f284347a66 | 708 | *d++ = *s++; |
humlet | 0:b6f284347a66 | 709 | *d++ = *s++; |
humlet | 0:b6f284347a66 | 710 | *d++ = *s++; |
humlet | 0:b6f284347a66 | 711 | } |
humlet | 0:b6f284347a66 | 712 | s += (mx - rx) * 3; /* Skip truncated pixels */ |
humlet | 0:b6f284347a66 | 713 | } |
humlet | 0:b6f284347a66 | 714 | } |
humlet | 0:b6f284347a66 | 715 | |
humlet | 0:b6f284347a66 | 716 | /* Convert RGB888 to RGB565 if needed */ |
humlet | 0:b6f284347a66 | 717 | if (JD_FORMAT == 1) { |
humlet | 0:b6f284347a66 | 718 | BYTE *s = (BYTE*)jd->workbuf; |
humlet | 0:b6f284347a66 | 719 | WORD w, *d = (WORD*)s; |
the_sz | 1:79e97662234d | 720 | JPG_UINT n = rx * ry; |
humlet | 0:b6f284347a66 | 721 | |
humlet | 0:b6f284347a66 | 722 | do { |
humlet | 0:b6f284347a66 | 723 | w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ |
humlet | 0:b6f284347a66 | 724 | w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ |
humlet | 0:b6f284347a66 | 725 | w |= *s++ >> 3; /* -----------BBBBB */ |
humlet | 0:b6f284347a66 | 726 | *d++ = w; |
humlet | 0:b6f284347a66 | 727 | } while (--n); |
humlet | 0:b6f284347a66 | 728 | } |
humlet | 0:b6f284347a66 | 729 | |
humlet | 0:b6f284347a66 | 730 | /* Output the RGB rectangular */ |
humlet | 0:b6f284347a66 | 731 | return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; |
humlet | 0:b6f284347a66 | 732 | } |
humlet | 0:b6f284347a66 | 733 | |
humlet | 0:b6f284347a66 | 734 | |
humlet | 0:b6f284347a66 | 735 | |
humlet | 0:b6f284347a66 | 736 | |
humlet | 0:b6f284347a66 | 737 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 738 | /* Process restart interval */ |
humlet | 0:b6f284347a66 | 739 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 740 | |
humlet | 0:b6f284347a66 | 741 | static |
humlet | 0:b6f284347a66 | 742 | JRESULT restart ( |
humlet | 0:b6f284347a66 | 743 | JDEC* jd, /* Pointer to the decompressor object */ |
humlet | 0:b6f284347a66 | 744 | WORD rstn /* Expected restert sequense number */ |
humlet | 0:b6f284347a66 | 745 | ) |
humlet | 0:b6f284347a66 | 746 | { |
the_sz | 1:79e97662234d | 747 | JPG_UINT i, dc; |
humlet | 0:b6f284347a66 | 748 | WORD d; |
humlet | 0:b6f284347a66 | 749 | BYTE *dp; |
humlet | 0:b6f284347a66 | 750 | |
humlet | 0:b6f284347a66 | 751 | |
humlet | 0:b6f284347a66 | 752 | /* Discard padding bits and get two bytes from the input stream */ |
humlet | 0:b6f284347a66 | 753 | dp = jd->dptr; |
humlet | 0:b6f284347a66 | 754 | dc = jd->dctr; |
humlet | 0:b6f284347a66 | 755 | d = 0; |
humlet | 0:b6f284347a66 | 756 | for (i = 0; i < 2; i++) { |
humlet | 0:b6f284347a66 | 757 | if (!dc) { /* No input data is available, re-fill input buffer */ |
humlet | 0:b6f284347a66 | 758 | dp = jd->inbuf; |
humlet | 0:b6f284347a66 | 759 | dc = jd->infunc(jd, dp, JD_SZBUF); |
humlet | 0:b6f284347a66 | 760 | if (!dc) return JDR_INP; |
humlet | 0:b6f284347a66 | 761 | } else { |
humlet | 0:b6f284347a66 | 762 | dp++; |
humlet | 0:b6f284347a66 | 763 | } |
humlet | 0:b6f284347a66 | 764 | dc--; |
humlet | 0:b6f284347a66 | 765 | d = (d << 8) | *dp; /* Get a byte */ |
humlet | 0:b6f284347a66 | 766 | } |
humlet | 0:b6f284347a66 | 767 | jd->dptr = dp; |
humlet | 0:b6f284347a66 | 768 | jd->dctr = dc; |
humlet | 0:b6f284347a66 | 769 | jd->dmsk = 0; |
humlet | 0:b6f284347a66 | 770 | |
humlet | 0:b6f284347a66 | 771 | /* Check the marker */ |
humlet | 0:b6f284347a66 | 772 | if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) |
humlet | 0:b6f284347a66 | 773 | return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ |
humlet | 0:b6f284347a66 | 774 | |
humlet | 0:b6f284347a66 | 775 | /* Reset DC offset */ |
humlet | 0:b6f284347a66 | 776 | jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; |
humlet | 0:b6f284347a66 | 777 | |
humlet | 0:b6f284347a66 | 778 | return JDR_OK; |
humlet | 0:b6f284347a66 | 779 | } |
humlet | 0:b6f284347a66 | 780 | |
humlet | 0:b6f284347a66 | 781 | |
humlet | 0:b6f284347a66 | 782 | |
humlet | 0:b6f284347a66 | 783 | |
humlet | 0:b6f284347a66 | 784 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 785 | /* Analyze the JPEG image and Initialize decompressor object */ |
humlet | 0:b6f284347a66 | 786 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 787 | |
humlet | 0:b6f284347a66 | 788 | #define LDB_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr))<<8)|(WORD)*(BYTE*)((ptr)+1)) |
humlet | 0:b6f284347a66 | 789 | |
humlet | 0:b6f284347a66 | 790 | |
humlet | 0:b6f284347a66 | 791 | JRESULT |
the_sz | 1:79e97662234d | 792 | //JPG_INT |
humlet | 0:b6f284347a66 | 793 | jd_prepare ( |
humlet | 0:b6f284347a66 | 794 | JDEC* jd, /* Blank decompressor object */ |
the_sz | 1:79e97662234d | 795 | JPG_UINT (*infunc)(JDEC*, BYTE*, JPG_UINT), /* JPEG strem input function */ |
humlet | 0:b6f284347a66 | 796 | void* pool, /* Working buffer for the decompression session */ |
the_sz | 1:79e97662234d | 797 | JPG_UINT sz_pool, /* Size of working buffer */ |
humlet | 0:b6f284347a66 | 798 | void* dev /* I/O device identifier for the session */ |
humlet | 0:b6f284347a66 | 799 | ) |
humlet | 0:b6f284347a66 | 800 | { |
humlet | 0:b6f284347a66 | 801 | BYTE *seg, b; |
humlet | 0:b6f284347a66 | 802 | WORD marker; |
humlet | 0:b6f284347a66 | 803 | DWORD ofs; |
the_sz | 1:79e97662234d | 804 | JPG_UINT n, i, j, len; |
humlet | 0:b6f284347a66 | 805 | JRESULT rc; |
humlet | 0:b6f284347a66 | 806 | |
humlet | 0:b6f284347a66 | 807 | |
humlet | 0:b6f284347a66 | 808 | if (!pool) return JDR_PAR; |
humlet | 0:b6f284347a66 | 809 | |
humlet | 0:b6f284347a66 | 810 | jd->pool = pool; /* Work memroy */ |
humlet | 0:b6f284347a66 | 811 | jd->sz_pool = sz_pool; /* Size of given work memory */ |
humlet | 0:b6f284347a66 | 812 | jd->infunc = infunc; /* Stream input function */ |
humlet | 0:b6f284347a66 | 813 | jd->device = dev; /* I/O device identifier */ |
humlet | 0:b6f284347a66 | 814 | jd->nrst = 0; /* No restart interval (default) */ |
humlet | 0:b6f284347a66 | 815 | |
humlet | 0:b6f284347a66 | 816 | for (i = 0; i < 2; i++) { /* Nulls pointers */ |
humlet | 0:b6f284347a66 | 817 | for (j = 0; j < 2; j++) { |
humlet | 0:b6f284347a66 | 818 | jd->huffbits[i][j] = 0; |
humlet | 0:b6f284347a66 | 819 | jd->huffcode[i][j] = 0; |
humlet | 0:b6f284347a66 | 820 | jd->huffdata[i][j] = 0; |
humlet | 0:b6f284347a66 | 821 | } |
humlet | 0:b6f284347a66 | 822 | } |
humlet | 0:b6f284347a66 | 823 | for (i = 0; i < 4; i++) jd->qttbl[i] = 0; |
humlet | 0:b6f284347a66 | 824 | |
humlet | 0:b6f284347a66 | 825 | jd->inbuf = seg = (BYTE*)alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ |
humlet | 0:b6f284347a66 | 826 | if (!seg) return JDR_MEM1; |
humlet | 0:b6f284347a66 | 827 | |
humlet | 0:b6f284347a66 | 828 | if (jd->infunc(jd, seg, 2) != 2) return JDR_INP;/* Check SOI marker */ |
humlet | 0:b6f284347a66 | 829 | if (LDB_WORD(seg) != 0xFFD8) return JDR_FMT1; /* Err: SOI is not detected */ |
humlet | 0:b6f284347a66 | 830 | ofs = 2; |
humlet | 0:b6f284347a66 | 831 | |
humlet | 0:b6f284347a66 | 832 | for (;;) { |
humlet | 0:b6f284347a66 | 833 | /* Get a JPEG marker */ |
humlet | 0:b6f284347a66 | 834 | if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; |
humlet | 0:b6f284347a66 | 835 | marker = LDB_WORD(seg); /* Marker */ |
humlet | 0:b6f284347a66 | 836 | len = LDB_WORD(seg + 2); /* Length field */ |
humlet | 0:b6f284347a66 | 837 | if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; |
humlet | 0:b6f284347a66 | 838 | len -= 2; /* Content size excluding length field */ |
humlet | 0:b6f284347a66 | 839 | ofs += 4 + len; /* Number of bytes loaded */ |
humlet | 0:b6f284347a66 | 840 | |
humlet | 0:b6f284347a66 | 841 | switch (marker & 0xFF) { |
humlet | 0:b6f284347a66 | 842 | case 0xC0: /* SOF0 (baseline JPEG) */ |
humlet | 0:b6f284347a66 | 843 | /* Load segment data */ |
humlet | 0:b6f284347a66 | 844 | if (len > JD_SZBUF) return JDR_MEM2; |
humlet | 0:b6f284347a66 | 845 | if (jd->infunc(jd, seg, len) != len) return JDR_INP; |
humlet | 0:b6f284347a66 | 846 | |
humlet | 0:b6f284347a66 | 847 | jd->width = LDB_WORD(seg+3); /* Image width in unit of pixel */ |
humlet | 0:b6f284347a66 | 848 | jd->height = LDB_WORD(seg+1); /* Image height in unit of pixel */ |
humlet | 0:b6f284347a66 | 849 | if (seg[5] != 3) return JDR_FMT3; /* Err: Supports only Y/Cb/Cr format */ |
humlet | 0:b6f284347a66 | 850 | |
humlet | 0:b6f284347a66 | 851 | /* Check three image components */ |
humlet | 0:b6f284347a66 | 852 | for (i = 0; i < 3; i++) { |
humlet | 0:b6f284347a66 | 853 | b = seg[7 + 3 * i]; /* Get sampling factor */ |
humlet | 0:b6f284347a66 | 854 | if (!i) { /* Y component */ |
humlet | 0:b6f284347a66 | 855 | if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */ |
humlet | 0:b6f284347a66 | 856 | return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ |
humlet | 0:b6f284347a66 | 857 | jd->msx = b >> 4; |
humlet | 0:b6f284347a66 | 858 | jd->msy = b & 15; /* Size of MCU [blocks] */ |
humlet | 0:b6f284347a66 | 859 | } else { /* Cb/Cr component */ |
humlet | 0:b6f284347a66 | 860 | if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ |
humlet | 0:b6f284347a66 | 861 | } |
humlet | 0:b6f284347a66 | 862 | b = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ |
humlet | 0:b6f284347a66 | 863 | if (b > 3) return JDR_FMT3; /* Err: Invalid ID */ |
humlet | 0:b6f284347a66 | 864 | jd->qtid[i] = b; |
humlet | 0:b6f284347a66 | 865 | } |
humlet | 0:b6f284347a66 | 866 | break; |
humlet | 0:b6f284347a66 | 867 | |
humlet | 0:b6f284347a66 | 868 | case 0xDD: /* DRI */ |
humlet | 0:b6f284347a66 | 869 | /* Load segment data */ |
humlet | 0:b6f284347a66 | 870 | if (len > JD_SZBUF) return JDR_MEM2; |
humlet | 0:b6f284347a66 | 871 | if (jd->infunc(jd, seg, len) != len) return JDR_INP; |
humlet | 0:b6f284347a66 | 872 | |
humlet | 0:b6f284347a66 | 873 | /* Get restart interval (MCUs) */ |
humlet | 0:b6f284347a66 | 874 | jd->nrst = LDB_WORD(seg); |
humlet | 0:b6f284347a66 | 875 | break; |
humlet | 0:b6f284347a66 | 876 | |
humlet | 0:b6f284347a66 | 877 | case 0xC4: /* DHT */ |
humlet | 0:b6f284347a66 | 878 | /* Load segment data */ |
humlet | 0:b6f284347a66 | 879 | if (len > JD_SZBUF) return JDR_MEM2; |
humlet | 0:b6f284347a66 | 880 | if (jd->infunc(jd, seg, len) != len) return JDR_INP; |
humlet | 0:b6f284347a66 | 881 | |
humlet | 0:b6f284347a66 | 882 | /* Create huffman tables */ |
humlet | 0:b6f284347a66 | 883 | rc = create_huffman_tbl(jd, seg, len); |
humlet | 0:b6f284347a66 | 884 | if (rc) return rc; |
humlet | 0:b6f284347a66 | 885 | break; |
humlet | 0:b6f284347a66 | 886 | |
humlet | 0:b6f284347a66 | 887 | case 0xDB: /* DQT */ |
humlet | 0:b6f284347a66 | 888 | /* Load segment data */ |
humlet | 0:b6f284347a66 | 889 | if (len > JD_SZBUF) return JDR_MEM2; |
humlet | 0:b6f284347a66 | 890 | if (jd->infunc(jd, seg, len) != len) return JDR_INP; |
humlet | 0:b6f284347a66 | 891 | |
humlet | 0:b6f284347a66 | 892 | /* Create de-quantizer tables */ |
humlet | 0:b6f284347a66 | 893 | rc = create_qt_tbl(jd, seg, len); |
humlet | 0:b6f284347a66 | 894 | if (rc) return rc; |
humlet | 0:b6f284347a66 | 895 | break; |
humlet | 0:b6f284347a66 | 896 | |
humlet | 0:b6f284347a66 | 897 | case 0xDA: /* SOS */ |
humlet | 0:b6f284347a66 | 898 | /* Load segment data */ |
humlet | 0:b6f284347a66 | 899 | if (len > JD_SZBUF) return JDR_MEM2; |
humlet | 0:b6f284347a66 | 900 | if (jd->infunc(jd, seg, len) != len) return JDR_INP; |
humlet | 0:b6f284347a66 | 901 | |
humlet | 0:b6f284347a66 | 902 | if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ |
humlet | 0:b6f284347a66 | 903 | |
humlet | 0:b6f284347a66 | 904 | if (seg[0] != 3) return JDR_FMT3; /* Err: Supports only three color components format */ |
humlet | 0:b6f284347a66 | 905 | |
humlet | 0:b6f284347a66 | 906 | /* Check if all tables corresponding to each components have been loaded */ |
humlet | 0:b6f284347a66 | 907 | for (i = 0; i < 3; i++) { |
humlet | 0:b6f284347a66 | 908 | b = seg[2 + 2 * i]; /* Get huffman table ID */ |
humlet | 0:b6f284347a66 | 909 | if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ |
humlet | 0:b6f284347a66 | 910 | b = i ? 1 : 0; |
humlet | 0:b6f284347a66 | 911 | if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */ |
humlet | 0:b6f284347a66 | 912 | return JDR_FMT1; /* Err: Huffman table not loaded */ |
humlet | 0:b6f284347a66 | 913 | if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */ |
humlet | 0:b6f284347a66 | 914 | } |
humlet | 0:b6f284347a66 | 915 | |
humlet | 0:b6f284347a66 | 916 | /* Allocate working buffer for MCU and RGB */ |
humlet | 0:b6f284347a66 | 917 | n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ |
humlet | 0:b6f284347a66 | 918 | if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ |
humlet | 0:b6f284347a66 | 919 | len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ |
humlet | 0:b6f284347a66 | 920 | if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ |
humlet | 0:b6f284347a66 | 921 | jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ |
humlet | 0:b6f284347a66 | 922 | if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 923 | jd->mcubuf = (BYTE*)alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ |
humlet | 0:b6f284347a66 | 924 | if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ |
humlet | 0:b6f284347a66 | 925 | |
humlet | 0:b6f284347a66 | 926 | /* Pre-load the JPEG data to extract it from the bit stream */ |
humlet | 0:b6f284347a66 | 927 | jd->dptr = seg; |
humlet | 0:b6f284347a66 | 928 | jd->dctr = 0; |
humlet | 0:b6f284347a66 | 929 | jd->dmsk = 0; /* Prepare to read bit stream */ |
humlet | 0:b6f284347a66 | 930 | if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ |
the_sz | 1:79e97662234d | 931 | jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (JPG_UINT)ofs); |
humlet | 0:b6f284347a66 | 932 | jd->dptr = seg + ofs - 1; |
humlet | 0:b6f284347a66 | 933 | } |
humlet | 0:b6f284347a66 | 934 | |
humlet | 0:b6f284347a66 | 935 | return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ |
humlet | 0:b6f284347a66 | 936 | |
humlet | 0:b6f284347a66 | 937 | case 0xC1: /* SOF1 */ |
humlet | 0:b6f284347a66 | 938 | case 0xC2: /* SOF2 */ |
humlet | 0:b6f284347a66 | 939 | case 0xC3: /* SOF3 */ |
humlet | 0:b6f284347a66 | 940 | case 0xC5: /* SOF5 */ |
humlet | 0:b6f284347a66 | 941 | case 0xC6: /* SOF6 */ |
humlet | 0:b6f284347a66 | 942 | case 0xC7: /* SOF7 */ |
humlet | 0:b6f284347a66 | 943 | case 0xC9: /* SOF9 */ |
humlet | 0:b6f284347a66 | 944 | case 0xCA: /* SOF10 */ |
humlet | 0:b6f284347a66 | 945 | case 0xCB: /* SOF11 */ |
humlet | 0:b6f284347a66 | 946 | case 0xCD: /* SOF13 */ |
humlet | 0:b6f284347a66 | 947 | case 0xCE: /* SOF14 */ |
humlet | 0:b6f284347a66 | 948 | case 0xCF: /* SOF15 */ |
humlet | 0:b6f284347a66 | 949 | case 0xD9: /* EOI */ |
humlet | 0:b6f284347a66 | 950 | return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ |
humlet | 0:b6f284347a66 | 951 | |
humlet | 0:b6f284347a66 | 952 | default: /* Unknown segment (comment, exif or etc..) */ |
humlet | 0:b6f284347a66 | 953 | /* Skip segment data */ |
humlet | 0:b6f284347a66 | 954 | if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */ |
humlet | 0:b6f284347a66 | 955 | return JDR_INP; |
humlet | 0:b6f284347a66 | 956 | } |
humlet | 0:b6f284347a66 | 957 | } |
humlet | 0:b6f284347a66 | 958 | } |
humlet | 0:b6f284347a66 | 959 | |
humlet | 0:b6f284347a66 | 960 | |
humlet | 0:b6f284347a66 | 961 | |
humlet | 0:b6f284347a66 | 962 | |
humlet | 0:b6f284347a66 | 963 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 964 | /* Start to decompress the JPEG picture */ |
humlet | 0:b6f284347a66 | 965 | /*-----------------------------------------------------------------------*/ |
humlet | 0:b6f284347a66 | 966 | |
humlet | 0:b6f284347a66 | 967 | JRESULT jd_decomp ( |
humlet | 0:b6f284347a66 | 968 | JDEC* jd, /* Initialized decompression object */ |
the_sz | 1:79e97662234d | 969 | JPG_UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ |
humlet | 0:b6f284347a66 | 970 | BYTE scale /* Output de-scaling factor (0 to 3) */ |
humlet | 0:b6f284347a66 | 971 | ) |
humlet | 0:b6f284347a66 | 972 | { |
the_sz | 1:79e97662234d | 973 | JPG_UINT x, y, mx, my; |
humlet | 0:b6f284347a66 | 974 | WORD rst, rsc; |
humlet | 0:b6f284347a66 | 975 | JRESULT rc; |
humlet | 0:b6f284347a66 | 976 | |
humlet | 0:b6f284347a66 | 977 | |
humlet | 0:b6f284347a66 | 978 | if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; |
humlet | 0:b6f284347a66 | 979 | jd->scale = scale; |
humlet | 0:b6f284347a66 | 980 | |
humlet | 0:b6f284347a66 | 981 | mx = jd->msx * 8; |
humlet | 0:b6f284347a66 | 982 | my = jd->msy * 8; /* Size of the MCU (pixel) */ |
humlet | 0:b6f284347a66 | 983 | |
humlet | 0:b6f284347a66 | 984 | jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ |
humlet | 0:b6f284347a66 | 985 | rst = rsc = 0; |
humlet | 0:b6f284347a66 | 986 | |
humlet | 0:b6f284347a66 | 987 | rc = JDR_OK; |
humlet | 0:b6f284347a66 | 988 | for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ |
humlet | 0:b6f284347a66 | 989 | for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ |
humlet | 0:b6f284347a66 | 990 | if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ |
humlet | 0:b6f284347a66 | 991 | rc = restart(jd, rsc++); |
humlet | 0:b6f284347a66 | 992 | if (rc != JDR_OK) {printf("jd_decomp KO 1\n");return rc;} |
humlet | 0:b6f284347a66 | 993 | rst = 1; |
humlet | 0:b6f284347a66 | 994 | } |
humlet | 0:b6f284347a66 | 995 | rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream and apply IDCT) */ |
humlet | 0:b6f284347a66 | 996 | if (rc != JDR_OK) {printf("jd_decomp KO 2\n");return rc;} |
humlet | 0:b6f284347a66 | 997 | rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (color space conversion, scaling and output) */ |
humlet | 0:b6f284347a66 | 998 | if (rc != JDR_OK) {printf("jd_decomp KO 3\n");return rc;} |
humlet | 0:b6f284347a66 | 999 | } |
humlet | 0:b6f284347a66 | 1000 | } |
humlet | 0:b6f284347a66 | 1001 | |
humlet | 0:b6f284347a66 | 1002 | return rc; |
humlet | 0:b6f284347a66 | 1003 | } |
humlet | 0:b6f284347a66 | 1004 | |
humlet | 0:b6f284347a66 | 1005 | |
humlet | 0:b6f284347a66 | 1006 |