working together with FATFileSystem

Fork of TinyJpgDec by Helmut Schmücker

Committer:
humlet
Date:
Sat Mar 22 18:00:42 2014 +0000
Revision:
0:b6f284347a66
Child:
1:79e97662234d
just ported to mbed

Who changed what in which revision?

UserRevisionLine numberNew 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
humlet 0:b6f284347a66 69 #define BYTECLIP(v) Clip8[(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 (
humlet 0:b6f284347a66 115 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 */
humlet 0:b6f284347a66 135 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
humlet 0:b6f284347a66 160 JRESULT // 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 */
humlet 0:b6f284347a66 164 UINT ndata /* Size of input data */
humlet 0:b6f284347a66 165 )
humlet 0:b6f284347a66 166 {
humlet 0:b6f284347a66 167 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
humlet 0:b6f284347a66 198 JRESULT //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 */
humlet 0:b6f284347a66 202 UINT ndata /* Size of input data */
humlet 0:b6f284347a66 203 )
humlet 0:b6f284347a66 204 {
humlet 0:b6f284347a66 205 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
humlet 0:b6f284347a66 258 INT bitext ( /* >=0: extracted data, <0: error code */
humlet 0:b6f284347a66 259 JDEC* jd, /* Pointer to the decompressor object */
humlet 0:b6f284347a66 260 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;
humlet 0:b6f284347a66 264 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);
humlet 0:b6f284347a66 277 if (!dc) return 0 - (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 */
humlet 0:b6f284347a66 284 if (*dp != 0) return 0 - (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
humlet 0:b6f284347a66 304 return (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
humlet 0:b6f284347a66 315 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;
humlet 0:b6f284347a66 323 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);
humlet 0:b6f284347a66 337 if (!dc) {printf("huffext KO 1\n");return 0 - (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)
humlet 0:b6f284347a66 345 {printf("huffext KO 2\n");return 0 - (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");
humlet 0:b6f284347a66 373 return 0 - (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;
humlet 0:b6f284347a66 392 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
humlet 0:b6f284347a66 498 //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 */
humlet 0:b6f284347a66 504 UINT blk, nby, nbc, i, z, id, cmp;
humlet 0:b6f284347a66 505 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
humlet 0:b6f284347a66 551 z = (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 */
humlet 0:b6f284347a66 588 UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
humlet 0:b6f284347a66 589 UINT x, /* MCU position in the image (left of the MCU) */
humlet 0:b6f284347a66 590 UINT y /* MCU position in the image (top of the MCU) */
humlet 0:b6f284347a66 591 )
humlet 0:b6f284347a66 592 {
humlet 0:b6f284347a66 593 const INT CVACC = (sizeof (INT) > 2) ? 1024 : 128;
humlet 0:b6f284347a66 594 UINT ix, iy, mx, my, rx, ry;
humlet 0:b6f284347a66 595 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 */
humlet 0:b6f284347a66 642 *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr) / CVACC);
humlet 0:b6f284347a66 643 *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC);
humlet 0:b6f284347a66 644 *rgb24++ = /* B */ BYTECLIP(yy + ((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) {
humlet 0:b6f284347a66 650 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 */
humlet 0:b6f284347a66 692 *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr / CVACC));
humlet 0:b6f284347a66 693 *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC);
humlet 0:b6f284347a66 694 *rgb24++ = /* B */ BYTECLIP(yy + ((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;
humlet 0:b6f284347a66 703 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;
humlet 0:b6f284347a66 720 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 {
humlet 0:b6f284347a66 747 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
humlet 0:b6f284347a66 792 //INT
humlet 0:b6f284347a66 793 jd_prepare (
humlet 0:b6f284347a66 794 JDEC* jd, /* Blank decompressor object */
humlet 0:b6f284347a66 795 UINT (*infunc)(JDEC*, BYTE*, UINT), /* JPEG strem input function */
humlet 0:b6f284347a66 796 void* pool, /* Working buffer for the decompression session */
humlet 0:b6f284347a66 797 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;
humlet 0:b6f284347a66 804 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 */
humlet 0:b6f284347a66 931 jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (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 */
humlet 0:b6f284347a66 969 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 {
humlet 0:b6f284347a66 973 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