Demonstration of the Bitmap rendering - reads BMP and JPG files in many format variants and renders to the screen.

Dependencies:   FlashFileSystem mbed RA8875

Bitmap and JPEG Demo

This demo publishes each graphic file from a list of files to the display. The graphic files can be BMP, JPG, or ICO. On the terminal it displays the filename and the return-code (in case of an error). This demo works as intended on the 480x272 display in either 8 or 16 bit per pixel mode and it should work on larger displays.

Items of interest to change and rebuild/test:

// Not all systems have the LocalFileSystem. Plug in the library and driver for yours.
LocalFileSystem local("local");             // Image source

TestImage_T TestImage[] = {
    { 0, 0, "/local/01601602.bmp"},
    { 0, 0, "/local/48027202.bmp"},
    { 0, 0, "/local/48027204.bmp"},
    { 0, 0, "/local/48027208.bmp"},
    { 0, 0, "/local/48027224.bmp"},
    { 0, 0, "/local/p480272.jpg"},
    { 0, 0, "/local/p480272.bmp"}
};

// deefine your screen size and color depth. 
#define SCREEN_W 480
#define SCREEN_H 272
#define SCREEN_BPP 16

LocalFileSystem may need to be altered to SDFileSystem (for example) and the corresponding paths in the TestImage array.

Also, the Screen size and bit per pixel color depth.

Images

The following image files are saved in different resolution and color depth. The first, and smallest, was simply for developing the monochrome support. Others are 4-bit color, 8-bit color, 24-bit color, and a mislabeled 1-bit color (shown as 02).

/media/uploads/WiredHome/testimages.zip

Committer:
WiredHome
Date:
Mon May 16 22:06:18 2016 +0000
Revision:
9:092f7ac73c03
Parent:
7:f96367d6e3e2
Child:
11:0c2ff405c1c1
Working - modified instrumentation

Who changed what in which revision?

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