├── picojpeg.sln ├── README.md ├── picojpeg.h ├── jpg2tga.vcproj ├── jpg2tga.c └── picojpeg.c /picojpeg.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual Studio 2005 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpg2tga", "jpg2tga.vcproj", "{83023E7E-D4CC-4E98-931A-64A1A1484785}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Debug|x64 = Debug|x64 9 | Release|Win32 = Release|Win32 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Debug|Win32.ActiveCfg = Debug|Win32 14 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Debug|Win32.Build.0 = Debug|Win32 15 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Debug|x64.ActiveCfg = Debug|x64 16 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Debug|x64.Build.0 = Debug|x64 17 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Release|Win32.ActiveCfg = Release|Win32 18 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Release|Win32.Build.0 = Release|Win32 19 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Release|x64.ActiveCfg = Release|x64 20 | {83023E7E-D4CC-4E98-931A-64A1A1484785}.Release|x64.Build.0 = Release|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # picojpeg 2 | Exported from http://code.google.com/p/picojpeg. Original author is Rich Geldreich at *richgel99 at gmail.com*. 3 | 4 | picojpeg is a public domain [JPEG](http://en.wikipedia.org/wiki/JPEG) decompressor written in plain C in a single source file [picojpeg.c](picojpeg.c) and a single header [picojpeg.h](picojpeg.h). It has several fairly unique properties that make it useful on small 8/16-bit embedded devices or in very memory constrained environments: 5 | 6 | * Optimized for minimal memory consumption: Uses only ~2.3KB of work memory. 7 | * Written assuming ROM code memory is more abundant than available RAM, which is the case on many microcontrollers. 8 | * All work arrays are limited to less than or equal to 256 bytes in size. 9 | * Written entirely in C, no reliance at all on the C run-time library (it includes no headers other than picojpeg.h), and does not use any dynamic memory allocation. 10 | * Simple API: Call pjpeg_decode_init() to initialize the decoder, and pjpeg_decode_mcu() to decode each MCU (Minimum Coded Unit). 11 | * Majority of expressions use only 8-bit integer operations, most variables are only 8-bits. 16-bit operations are only used when necessary. 12 | * Uses a Winograd IDCT to minimize the number of multiplies (5 per 1D IDCT, up to 80 total, each signed mul can be implemented as 16 bits*8 bits=24 bits). 13 | * Whenever possible, multiplies are limited to 8x8 or 16x8 bits, and are done against compile-time constants. 14 | * As of v1.1 the decoder supports a special "reduce" mode that returns a 1/8th size version of the compressed image. This mode skips several expensive steps: AC dequantization, IDCT, and per-pixel chroma upsampling/colorspace conversion. 15 | 16 | picojpeg has several disadantages and known issues compared to other implementations: 17 | 18 | * Quality is traded off for minimal RAM memory consumption and decent performance on small microcontrollers. For example, the chroma upsamplers use only box filtering, 8x8 multiplies, and minimal 16-bit operations so the decoder is not as accurate as it could be. 19 | * Only supports baseline sequential greyscale, or YCbCr H1V1, H1V2, H2V1, and H2V2 chroma sampling factors. Progressive JPEG's are not supported. 20 | * The Huffman decoder currently only reads a bit at a time to minimize RAM usage, so it's pretty slow. (However, on microcontroller CPU's with weak integer shift capabilities this method may be reasonable.) 21 | * All work arrays (approx. 2.3KB) are globals, because this resulted in the best code generation with the embedded compiler I was using during development. I'm assuming either this is not an issue, or the user is using a compiler that allows them to overlap these variables with other unrelated things. picojpeg is not thread safe because of this. 22 | 23 | A close variant of picojpeg has been successfully compiled and executed on Microchip's [PIC18F4610](http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010303) microcontroller using [SourceBoost Technologies BoostC embedded compiler](http://www.sourceboost.com/Products/BoostC/Overview.html). (Please email if you would like to see this variant.) picojpeg.c has also been used on the MSP430 and ARM Cortex-M4 CPU's. (For an example usage, see [Using picojpeg library on a PIC with ILI9341 320x240 LCD module](http://minhdanh2002.blogspot.com/2014/03/using-picojpeg-library-on-pic24-with.html)). 24 | 25 | The source distribution includes a sample VS2005 project and precompiled Win32/Win64 command line executables that convert JPG to TGA files using picojpeg for decompression. Sean Barrett's public domain [stb_image.c](http://nothings.org/stb_image.c) module is used to write TGA files. 26 | 27 | picojpeg was originally based off my [jpgd decompressor C++ class](http://code.google.com/p/jpgd/), which (on modern CPU's) is faster and more capable than picojpeg.c but uses a lot more memory and assumes int's are 32-bits. 28 | 29 | Here's picojpeg working on a 6809 CPU (a Tandy Color Computer 3), compiled using gcc6809: [picojpeg: Decoding Lena on a Tandy Color Computer 3](http://richg42.blogspot.com/2014/02/picojpeg-decoding-lena-on-tandy-color.html). 30 | 31 | ## Release History 32 | 33 | * v1.1 - 3/23/2020: Fixed unsigned/signed issue in macro, fixed overflow issue in decoder preventing the decode of very large JPEG's 34 | 35 | * v1.1 - Feb. 19, 2013: Dual licensed as both public domain and (where public domain is not acceptable) the MIT license. Please contact me for the source drop. 36 | * v1.1 - Feb. 9, 2013: Optimized the IDCT row/col loops to avoid the full inverse transform when only the DC component is non-zero, added "reduce" mode for fast 1/8th res decoding, better error handling, added support for H2V1/H1V2 chroma subsampling factors, ported jpg2tga.cpp to jpg2jpg.c (so all modules are written in plain C now), added code to compare picojpeg's decoded output vs. stb_image'c for testing/verification. 37 | * v1.0 - Nov. 10, 2010: Initial release. Derived from the original version which was tested on a PIC18F series CPU. 38 | 39 | ## Special Thanks 40 | 41 | Thanks to Daniel Swenson for contributing to picojpeg's development, and Chris Phoenix for his MSP430 patches. 42 | 43 | For any questions or problems with this module please contact Rich Geldreich at *richgel99 at gmail.com*. Here's my [twitter page](http://twitter.com/#!/richgel999). 44 | -------------------------------------------------------------------------------- /picojpeg.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // picojpeg - Public domain, Rich Geldreich 3 | //------------------------------------------------------------------------------ 4 | #ifndef PICOJPEG_H 5 | #define PICOJPEG_H 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | // Error codes 12 | enum 13 | { 14 | PJPG_NO_MORE_BLOCKS = 1, 15 | PJPG_BAD_DHT_COUNTS, 16 | PJPG_BAD_DHT_INDEX, 17 | PJPG_BAD_DHT_MARKER, 18 | PJPG_BAD_DQT_MARKER, 19 | PJPG_BAD_DQT_TABLE, 20 | PJPG_BAD_PRECISION, 21 | PJPG_BAD_HEIGHT, 22 | PJPG_BAD_WIDTH, 23 | PJPG_TOO_MANY_COMPONENTS, 24 | PJPG_BAD_SOF_LENGTH, 25 | PJPG_BAD_VARIABLE_MARKER, 26 | PJPG_BAD_DRI_LENGTH, 27 | PJPG_BAD_SOS_LENGTH, 28 | PJPG_BAD_SOS_COMP_ID, 29 | PJPG_W_EXTRA_BYTES_BEFORE_MARKER, 30 | PJPG_NO_ARITHMITIC_SUPPORT, 31 | PJPG_UNEXPECTED_MARKER, 32 | PJPG_NOT_JPEG, 33 | PJPG_UNSUPPORTED_MARKER, 34 | PJPG_BAD_DQT_LENGTH, 35 | PJPG_TOO_MANY_BLOCKS, 36 | PJPG_UNDEFINED_QUANT_TABLE, 37 | PJPG_UNDEFINED_HUFF_TABLE, 38 | PJPG_NOT_SINGLE_SCAN, 39 | PJPG_UNSUPPORTED_COLORSPACE, 40 | PJPG_UNSUPPORTED_SAMP_FACTORS, 41 | PJPG_DECODE_ERROR, 42 | PJPG_BAD_RESTART_MARKER, 43 | PJPG_ASSERTION_ERROR, 44 | PJPG_BAD_SOS_SPECTRAL, 45 | PJPG_BAD_SOS_SUCCESSIVE, 46 | PJPG_STREAM_READ_ERROR, 47 | PJPG_NOTENOUGHMEM, 48 | PJPG_UNSUPPORTED_COMP_IDENT, 49 | PJPG_UNSUPPORTED_QUANT_TABLE, 50 | PJPG_UNSUPPORTED_MODE, // picojpeg doesn't support progressive JPEG's 51 | }; 52 | 53 | // Scan types 54 | typedef enum 55 | { 56 | PJPG_GRAYSCALE, 57 | PJPG_YH1V1, 58 | PJPG_YH2V1, 59 | PJPG_YH1V2, 60 | PJPG_YH2V2 61 | } pjpeg_scan_type_t; 62 | 63 | typedef struct 64 | { 65 | // Image resolution 66 | int m_width; 67 | int m_height; 68 | 69 | // Number of components (1 or 3) 70 | int m_comps; 71 | 72 | // Total number of minimum coded units (MCU's) per row/col. 73 | int m_MCUSPerRow; 74 | int m_MCUSPerCol; 75 | 76 | // Scan type 77 | pjpeg_scan_type_t m_scanType; 78 | 79 | // MCU width/height in pixels (each is either 8 or 16 depending on the scan type) 80 | int m_MCUWidth; 81 | int m_MCUHeight; 82 | 83 | // m_pMCUBufR, m_pMCUBufG, and m_pMCUBufB are pointers to internal MCU Y or RGB pixel component buffers. 84 | // Each time pjpegDecodeMCU() is called successfully these buffers will be filled with 8x8 pixel blocks of Y or RGB pixels. 85 | // Each MCU consists of (m_MCUWidth/8)*(m_MCUHeight/8) Y/RGB blocks: 1 for greyscale/no subsampling, 2 for H1V2/H2V1, or 4 blocks for H2V2 sampling factors. 86 | // Each block is a contiguous array of 64 (8x8) bytes of a single component: either Y for grayscale images, or R, G or B components for color images. 87 | // 88 | // The 8x8 pixel blocks are organized in these byte arrays like this: 89 | // 90 | // PJPG_GRAYSCALE: Each MCU is decoded to a single block of 8x8 grayscale pixels. 91 | // Only the values in m_pMCUBufR are valid. Each 8 bytes is a row of pixels (raster order: left to right, top to bottom) from the 8x8 block. 92 | // 93 | // PJPG_H1V1: Each MCU contains is decoded to a single block of 8x8 RGB pixels. 94 | // 95 | // PJPG_YH2V1: Each MCU is decoded to 2 blocks, or 16x8 pixels. 96 | // The 2 RGB blocks are at byte offsets: 0, 64 97 | // 98 | // PJPG_YH1V2: Each MCU is decoded to 2 blocks, or 8x16 pixels. 99 | // The 2 RGB blocks are at byte offsets: 0, 100 | // 128 101 | // 102 | // PJPG_YH2V2: Each MCU is decoded to 4 blocks, or 16x16 pixels. 103 | // The 2x2 block array is organized at byte offsets: 0, 64, 104 | // 128, 192 105 | // 106 | // It is up to the caller to copy or blit these pixels from these buffers into the destination bitmap. 107 | unsigned char *m_pMCUBufR; 108 | unsigned char *m_pMCUBufG; 109 | unsigned char *m_pMCUBufB; 110 | } pjpeg_image_info_t; 111 | 112 | typedef unsigned char (*pjpeg_need_bytes_callback_t)(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data); 113 | 114 | // Initializes the decompressor. Returns 0 on success, or one of the above error codes on failure. 115 | // pNeed_bytes_callback will be called to fill the decompressor's internal input buffer. 116 | // If reduce is 1, only the first pixel of each block will be decoded. This mode is much faster because it skips the AC dequantization, IDCT and chroma upsampling of every image pixel. 117 | // Not thread safe. 118 | unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data, unsigned char reduce); 119 | 120 | // Decompresses the file's next MCU. Returns 0 on success, PJPG_NO_MORE_BLOCKS if no more blocks are available, or an error code. 121 | // Must be called a total of m_MCUSPerRow*m_MCUSPerCol times to completely decompress the image. 122 | // Not thread safe. 123 | unsigned char pjpeg_decode_mcu(void); 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif // PICOJPEG_H 130 | -------------------------------------------------------------------------------- /jpg2tga.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | 19 | 29 | 32 | 35 | 38 | 41 | 45 | 62 | 65 | 70 | 73 | 82 | 85 | 88 | 91 | 94 | 97 | 100 | 103 | 106 | 107 | 117 | 120 | 123 | 126 | 129 | 134 | 151 | 154 | 159 | 162 | 171 | 174 | 177 | 180 | 183 | 186 | 189 | 192 | 195 | 196 | 207 | 210 | 213 | 216 | 219 | 223 | 245 | 248 | 253 | 256 | 264 | 267 | 270 | 273 | 276 | 279 | 282 | 285 | 288 | 289 | 300 | 303 | 306 | 309 | 312 | 317 | 339 | 342 | 347 | 350 | 358 | 361 | 364 | 367 | 370 | 373 | 376 | 379 | 382 | 383 | 384 | 385 | 386 | 387 | 391 | 394 | 395 | 398 | 399 | 403 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | -------------------------------------------------------------------------------- /jpg2tga.c: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // jpg2tga.c 3 | // JPEG to TGA file conversion example program. 4 | // Public domain, Rich Geldreich 5 | // Last updated Nov. 26, 2010 6 | //------------------------------------------------------------------------------ 7 | #include "picojpeg.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "stb_image.c" 16 | //------------------------------------------------------------------------------ 17 | #ifndef max 18 | #define max(a,b) (((a) > (b)) ? (a) : (b)) 19 | #endif 20 | #ifndef min 21 | #define min(a,b) (((a) < (b)) ? (a) : (b)) 22 | #endif 23 | //------------------------------------------------------------------------------ 24 | typedef unsigned char uint8; 25 | typedef unsigned int uint; 26 | //------------------------------------------------------------------------------ 27 | static int print_usage() 28 | { 29 | printf("Usage: jpg2tga [source_file] [dest_file] \n"); 30 | printf("source_file: JPEG file to decode. Note: Progressive files are not supported.\n"); 31 | printf("dest_file: Output .TGA file\n"); 32 | printf("reduce: Optional, if 1 the JPEG file is quickly decoded to ~1/8th resolution.\n"); 33 | printf("\n"); 34 | printf("Outputs 8-bit grayscale or truecolor 24-bit TGA files.\n"); 35 | return EXIT_FAILURE; 36 | } 37 | //------------------------------------------------------------------------------ 38 | static FILE *g_pInFile; 39 | static uint g_nInFileSize; 40 | static uint g_nInFileOfs; 41 | //------------------------------------------------------------------------------ 42 | unsigned char pjpeg_need_bytes_callback(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data) 43 | { 44 | uint n; 45 | pCallback_data; 46 | 47 | n = min(g_nInFileSize - g_nInFileOfs, buf_size); 48 | if (n && (fread(pBuf, 1, n, g_pInFile) != n)) 49 | return PJPG_STREAM_READ_ERROR; 50 | *pBytes_actually_read = (unsigned char)(n); 51 | g_nInFileOfs += n; 52 | return 0; 53 | } 54 | //------------------------------------------------------------------------------ 55 | // Loads JPEG image from specified file. Returns NULL on failure. 56 | // On success, the malloc()'d image's width/height is written to *x and *y, and 57 | // the number of components (1 or 3) is written to *comps. 58 | // pScan_type can be NULL, if not it'll be set to the image's pjpeg_scan_type_t. 59 | // Not thread safe. 60 | // If reduce is non-zero, the image will be more quickly decoded at approximately 61 | // 1/8 resolution (the actual returned resolution will depend on the JPEG 62 | // subsampling factor). 63 | uint8 *pjpeg_load_from_file(const char *pFilename, int *x, int *y, int *comps, pjpeg_scan_type_t *pScan_type, int reduce) 64 | { 65 | pjpeg_image_info_t image_info; 66 | int mcu_x = 0; 67 | int mcu_y = 0; 68 | uint row_pitch; 69 | uint8 *pImage; 70 | uint8 status; 71 | uint decoded_width, decoded_height; 72 | uint row_blocks_per_mcu, col_blocks_per_mcu; 73 | 74 | *x = 0; 75 | *y = 0; 76 | *comps = 0; 77 | if (pScan_type) *pScan_type = PJPG_GRAYSCALE; 78 | 79 | g_pInFile = fopen(pFilename, "rb"); 80 | if (!g_pInFile) 81 | return NULL; 82 | 83 | g_nInFileOfs = 0; 84 | 85 | fseek(g_pInFile, 0, SEEK_END); 86 | g_nInFileSize = ftell(g_pInFile); 87 | fseek(g_pInFile, 0, SEEK_SET); 88 | 89 | status = pjpeg_decode_init(&image_info, pjpeg_need_bytes_callback, NULL, (unsigned char)reduce); 90 | 91 | if (status) 92 | { 93 | printf("pjpeg_decode_init() failed with status %u\n", status); 94 | if (status == PJPG_UNSUPPORTED_MODE) 95 | { 96 | printf("Progressive JPEG files are not supported.\n"); 97 | } 98 | 99 | fclose(g_pInFile); 100 | return NULL; 101 | } 102 | 103 | if (pScan_type) 104 | *pScan_type = image_info.m_scanType; 105 | 106 | // In reduce mode output 1 pixel per 8x8 block. 107 | decoded_width = reduce ? (image_info.m_MCUSPerRow * image_info.m_MCUWidth) / 8 : image_info.m_width; 108 | decoded_height = reduce ? (image_info.m_MCUSPerCol * image_info.m_MCUHeight) / 8 : image_info.m_height; 109 | 110 | row_pitch = decoded_width * image_info.m_comps; 111 | pImage = (uint8 *)malloc(row_pitch * decoded_height); 112 | if (!pImage) 113 | { 114 | fclose(g_pInFile); 115 | return NULL; 116 | } 117 | 118 | row_blocks_per_mcu = image_info.m_MCUWidth >> 3; 119 | col_blocks_per_mcu = image_info.m_MCUHeight >> 3; 120 | 121 | for ( ; ; ) 122 | { 123 | int y, x; 124 | uint8 *pDst_row; 125 | 126 | status = pjpeg_decode_mcu(); 127 | 128 | if (status) 129 | { 130 | if (status != PJPG_NO_MORE_BLOCKS) 131 | { 132 | printf("pjpeg_decode_mcu() failed with status %u\n", status); 133 | 134 | free(pImage); 135 | fclose(g_pInFile); 136 | return NULL; 137 | } 138 | 139 | break; 140 | } 141 | 142 | if (mcu_y >= image_info.m_MCUSPerCol) 143 | { 144 | free(pImage); 145 | fclose(g_pInFile); 146 | return NULL; 147 | } 148 | 149 | if (reduce) 150 | { 151 | // In reduce mode, only the first pixel of each 8x8 block is valid. 152 | pDst_row = pImage + mcu_y * col_blocks_per_mcu * row_pitch + mcu_x * row_blocks_per_mcu * image_info.m_comps; 153 | if (image_info.m_scanType == PJPG_GRAYSCALE) 154 | { 155 | *pDst_row = image_info.m_pMCUBufR[0]; 156 | } 157 | else 158 | { 159 | uint y, x; 160 | for (y = 0; y < col_blocks_per_mcu; y++) 161 | { 162 | uint src_ofs = (y * 128U); 163 | for (x = 0; x < row_blocks_per_mcu; x++) 164 | { 165 | pDst_row[0] = image_info.m_pMCUBufR[src_ofs]; 166 | pDst_row[1] = image_info.m_pMCUBufG[src_ofs]; 167 | pDst_row[2] = image_info.m_pMCUBufB[src_ofs]; 168 | pDst_row += 3; 169 | src_ofs += 64; 170 | } 171 | 172 | pDst_row += row_pitch - 3 * row_blocks_per_mcu; 173 | } 174 | } 175 | } 176 | else 177 | { 178 | // Copy MCU's pixel blocks into the destination bitmap. 179 | pDst_row = pImage + (mcu_y * image_info.m_MCUHeight) * row_pitch + (mcu_x * image_info.m_MCUWidth * image_info.m_comps); 180 | 181 | for (y = 0; y < image_info.m_MCUHeight; y += 8) 182 | { 183 | const int by_limit = min(8, image_info.m_height - (mcu_y * image_info.m_MCUHeight + y)); 184 | 185 | for (x = 0; x < image_info.m_MCUWidth; x += 8) 186 | { 187 | uint8 *pDst_block = pDst_row + x * image_info.m_comps; 188 | 189 | // Compute source byte offset of the block in the decoder's MCU buffer. 190 | uint src_ofs = (x * 8U) + (y * 16U); 191 | const uint8 *pSrcR = image_info.m_pMCUBufR + src_ofs; 192 | const uint8 *pSrcG = image_info.m_pMCUBufG + src_ofs; 193 | const uint8 *pSrcB = image_info.m_pMCUBufB + src_ofs; 194 | 195 | const int bx_limit = min(8, image_info.m_width - (mcu_x * image_info.m_MCUWidth + x)); 196 | 197 | if (image_info.m_scanType == PJPG_GRAYSCALE) 198 | { 199 | int bx, by; 200 | for (by = 0; by < by_limit; by++) 201 | { 202 | uint8 *pDst = pDst_block; 203 | 204 | for (bx = 0; bx < bx_limit; bx++) 205 | *pDst++ = *pSrcR++; 206 | 207 | pSrcR += (8 - bx_limit); 208 | 209 | pDst_block += row_pitch; 210 | } 211 | } 212 | else 213 | { 214 | int bx, by; 215 | for (by = 0; by < by_limit; by++) 216 | { 217 | uint8 *pDst = pDst_block; 218 | 219 | for (bx = 0; bx < bx_limit; bx++) 220 | { 221 | pDst[0] = *pSrcR++; 222 | pDst[1] = *pSrcG++; 223 | pDst[2] = *pSrcB++; 224 | pDst += 3; 225 | } 226 | 227 | pSrcR += (8 - bx_limit); 228 | pSrcG += (8 - bx_limit); 229 | pSrcB += (8 - bx_limit); 230 | 231 | pDst_block += row_pitch; 232 | } 233 | } 234 | } 235 | 236 | pDst_row += (row_pitch * 8); 237 | } 238 | } 239 | 240 | mcu_x++; 241 | if (mcu_x == image_info.m_MCUSPerRow) 242 | { 243 | mcu_x = 0; 244 | mcu_y++; 245 | } 246 | } 247 | 248 | fclose(g_pInFile); 249 | 250 | *x = decoded_width; 251 | *y = decoded_height; 252 | *comps = image_info.m_comps; 253 | 254 | return pImage; 255 | } 256 | //------------------------------------------------------------------------------ 257 | typedef struct image_compare_results_tag 258 | { 259 | double max_err; 260 | double mean; 261 | double mean_squared; 262 | double root_mean_squared; 263 | double peak_snr; 264 | } image_compare_results; 265 | 266 | static void get_pixel(int* pDst, const uint8 *pSrc, int luma_only, int num_comps) 267 | { 268 | int r, g, b; 269 | if (num_comps == 1) 270 | { 271 | r = g = b = pSrc[0]; 272 | } 273 | else if (luma_only) 274 | { 275 | const int YR = 19595, YG = 38470, YB = 7471; 276 | r = g = b = (pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) / 65536; 277 | } 278 | else 279 | { 280 | r = pSrc[0]; g = pSrc[1]; b = pSrc[2]; 281 | } 282 | pDst[0] = r; pDst[1] = g; pDst[2] = b; 283 | } 284 | 285 | // Compute image error metrics. 286 | static void image_compare(image_compare_results *pResults, int width, int height, const uint8 *pComp_image, int comp_image_comps, const uint8 *pUncomp_image_data, int uncomp_comps, int luma_only) 287 | { 288 | double hist[256]; 289 | double sum = 0.0f, sum2 = 0.0f; 290 | double total_values; 291 | const uint first_channel = 0, num_channels = 3; 292 | int x, y; 293 | uint i; 294 | 295 | memset(hist, 0, sizeof(hist)); 296 | 297 | for (y = 0; y < height; y++) 298 | { 299 | for (x = 0; x < width; x++) 300 | { 301 | uint c; 302 | int a[3]; 303 | int b[3]; 304 | 305 | get_pixel(a, pComp_image + (y * width + x) * comp_image_comps, luma_only, comp_image_comps); 306 | get_pixel(b, pUncomp_image_data + (y * width + x) * uncomp_comps, luma_only, uncomp_comps); 307 | 308 | for (c = 0; c < num_channels; c++) 309 | hist[labs(a[first_channel + c] - b[first_channel + c])]++; 310 | } 311 | } 312 | 313 | pResults->max_err = 0; 314 | 315 | for (i = 0; i < 256; i++) 316 | { 317 | double x; 318 | if (!hist[i]) 319 | continue; 320 | if (i > pResults->max_err) 321 | pResults->max_err = i; 322 | x = i * hist[i]; 323 | sum += x; 324 | sum2 += i * x; 325 | } 326 | 327 | // See http://bmrc.berkeley.edu/courseware/cs294/fall97/assignment/psnr.html 328 | total_values = width * height; 329 | 330 | pResults->mean = sum / total_values; 331 | pResults->mean_squared = sum2 / total_values; 332 | 333 | pResults->root_mean_squared = sqrt(pResults->mean_squared); 334 | 335 | if (!pResults->root_mean_squared) 336 | pResults->peak_snr = 1e+10f; 337 | else 338 | pResults->peak_snr = log10(255.0f / pResults->root_mean_squared) * 20.0f; 339 | } 340 | //------------------------------------------------------------------------------ 341 | int main(int arg_c, char *arg_v[]) 342 | { 343 | int n = 1; 344 | const char *pSrc_filename; 345 | const char *pDst_filename; 346 | int width, height, comps; 347 | pjpeg_scan_type_t scan_type; 348 | const char* p = "?"; 349 | uint8 *pImage; 350 | int reduce = 0; 351 | 352 | printf("picojpeg example v1.1, Rich Geldreich , Compiled " __TIME__ " " __DATE__ "\n"); 353 | 354 | if ((arg_c < 3) || (arg_c > 4)) 355 | return print_usage(); 356 | 357 | pSrc_filename = arg_v[n++]; 358 | pDst_filename = arg_v[n++]; 359 | if (arg_c == 4) 360 | reduce = atoi(arg_v[n++]) != 0; 361 | 362 | printf("Source file: \"%s\"\n", pSrc_filename); 363 | printf("Destination file: \"%s\"\n", pDst_filename); 364 | printf("Reduce during decoding: %u\n", reduce); 365 | 366 | pImage = pjpeg_load_from_file(pSrc_filename, &width, &height, &comps, &scan_type, reduce); 367 | if (!pImage) 368 | { 369 | printf("Failed loading source image!\n"); 370 | return EXIT_FAILURE; 371 | } 372 | 373 | printf("Width: %i, Height: %i, Comps: %i\n", width, height, comps); 374 | 375 | switch (scan_type) 376 | { 377 | case PJPG_GRAYSCALE: p = "GRAYSCALE"; break; 378 | case PJPG_YH1V1: p = "H1V1"; break; 379 | case PJPG_YH2V1: p = "H2V1"; break; 380 | case PJPG_YH1V2: p = "H1V2"; break; 381 | case PJPG_YH2V2: p = "H2V2"; break; 382 | } 383 | printf("Scan type: %s\n", p); 384 | 385 | if (!stbi_write_tga(pDst_filename, width, height, comps, pImage)) 386 | { 387 | printf("Failed writing image to destination file!\n"); 388 | return EXIT_FAILURE; 389 | } 390 | 391 | printf("Successfully wrote destination file %s\n", pDst_filename); 392 | 393 | // Now load the JPEG file using stb_image.c and compare the decoded pixels vs. picojpeg's. 394 | // stb_image.c uses filtered and higher precision chroma upsampling, and a higher precision IDCT vs. picojpeg so some error is to be expected. 395 | if (!reduce) 396 | { 397 | int stb_width = 0, stb_height = 0, stb_actual_comps = 0, stb_req_comps = 0; 398 | unsigned char *pSTB_image_data; 399 | stb_req_comps = (scan_type == PJPG_GRAYSCALE) ? 1 : 3; 400 | pSTB_image_data = stbi_load(pSrc_filename, &stb_width, &stb_height, &stb_actual_comps, stb_req_comps); 401 | if (!pSTB_image_data) 402 | { 403 | printf("Failed decoding using stb_image.c!\n"); 404 | } 405 | else if ((stb_width != width) || (stb_height != height) || (stb_actual_comps != comps)) 406 | { 407 | printf("Image was successfully decompresed using stb_image.c, but the resulting dimensions/comps differ from picojpeg's!\n"); 408 | } 409 | else 410 | { 411 | image_compare_results results; 412 | memset(&results, 0, sizeof(results)); 413 | 414 | image_compare(&results, width, height, pImage, comps, pSTB_image_data, stb_actual_comps, (scan_type == PJPG_GRAYSCALE)); 415 | 416 | printf("picojpeg vs. stb_image:\n"); 417 | printf("Error Max: %f, Mean: %f, Mean^2: %f, RMSE: %f, PSNR: %f\n", results.max_err, results.mean, results.mean_squared, results.root_mean_squared, results.peak_snr); 418 | } 419 | 420 | free(pSTB_image_data); 421 | } 422 | 423 | free(pImage); 424 | 425 | return EXIT_SUCCESS; 426 | } 427 | //------------------------------------------------------------------------------ 428 | 429 | -------------------------------------------------------------------------------- /picojpeg.c: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // picojpeg.c v1.1 - Public domain, Rich Geldreich 3 | // Nov. 27, 2010 - Initial release 4 | // Feb. 9, 2013 - Added H1V2/H2V1 support, cleaned up macros, signed shift fixes 5 | // Also integrated and tested changes from Chris Phoenix . 6 | //------------------------------------------------------------------------------ 7 | #include "picojpeg.h" 8 | //------------------------------------------------------------------------------ 9 | // Set to 1 if right shifts on signed ints are always unsigned (logical) shifts 10 | // When 1, arithmetic right shifts will be emulated by using a logical shift 11 | // with special case code to ensure the sign bit is replicated. 12 | #define PJPG_RIGHT_SHIFT_IS_ALWAYS_UNSIGNED 0 13 | 14 | // Define PJPG_INLINE to "inline" if your C compiler supports explicit inlining 15 | #define PJPG_INLINE 16 | //------------------------------------------------------------------------------ 17 | typedef unsigned char uint8; 18 | typedef unsigned short uint16; 19 | typedef signed char int8; 20 | typedef signed short int16; 21 | //------------------------------------------------------------------------------ 22 | #if PJPG_RIGHT_SHIFT_IS_ALWAYS_UNSIGNED 23 | static int16 replicateSignBit16(int8 n) 24 | { 25 | switch (n) 26 | { 27 | case 0: return 0x0000; 28 | case 1: return 0x8000; 29 | case 2: return 0xC000; 30 | case 3: return 0xE000; 31 | case 4: return 0xF000; 32 | case 5: return 0xF800; 33 | case 6: return 0xFC00; 34 | case 7: return 0xFE00; 35 | case 8: return 0xFF00; 36 | case 9: return 0xFF80; 37 | case 10: return 0xFFC0; 38 | case 11: return 0xFFE0; 39 | case 12: return 0xFFF0; 40 | case 13: return 0xFFF8; 41 | case 14: return 0xFFFC; 42 | case 15: return 0xFFFE; 43 | default: return 0xFFFF; 44 | } 45 | } 46 | static PJPG_INLINE int16 arithmeticRightShiftN16(int16 x, int8 n) 47 | { 48 | int16 r = (uint16)x >> (uint8)n; 49 | if (x < 0) 50 | r |= replicateSignBit16(n); 51 | return r; 52 | } 53 | static PJPG_INLINE long arithmeticRightShift8L(long x) 54 | { 55 | long r = (unsigned long)x >> 8U; 56 | if (x < 0) 57 | r |= ~(~(unsigned long)0U >> 8U); 58 | return r; 59 | } 60 | #define PJPG_ARITH_SHIFT_RIGHT_N_16(x, n) arithmeticRightShiftN16(x, n) 61 | #define PJPG_ARITH_SHIFT_RIGHT_8_L(x) arithmeticRightShift8L(x) 62 | #else 63 | #define PJPG_ARITH_SHIFT_RIGHT_N_16(x, n) ((x) >> (n)) 64 | #define PJPG_ARITH_SHIFT_RIGHT_8_L(x) ((x) >> 8) 65 | #endif 66 | //------------------------------------------------------------------------------ 67 | // Change as needed - the PJPG_MAX_WIDTH/PJPG_MAX_HEIGHT checks are only present 68 | // to quickly detect bogus files. 69 | #define PJPG_MAX_WIDTH 16384 70 | #define PJPG_MAX_HEIGHT 16384 71 | #define PJPG_MAXCOMPSINSCAN 3 72 | //------------------------------------------------------------------------------ 73 | typedef enum 74 | { 75 | M_SOF0 = 0xC0, 76 | M_SOF1 = 0xC1, 77 | M_SOF2 = 0xC2, 78 | M_SOF3 = 0xC3, 79 | 80 | M_SOF5 = 0xC5, 81 | M_SOF6 = 0xC6, 82 | M_SOF7 = 0xC7, 83 | 84 | M_JPG = 0xC8, 85 | M_SOF9 = 0xC9, 86 | M_SOF10 = 0xCA, 87 | M_SOF11 = 0xCB, 88 | 89 | M_SOF13 = 0xCD, 90 | M_SOF14 = 0xCE, 91 | M_SOF15 = 0xCF, 92 | 93 | M_DHT = 0xC4, 94 | 95 | M_DAC = 0xCC, 96 | 97 | M_RST0 = 0xD0, 98 | M_RST1 = 0xD1, 99 | M_RST2 = 0xD2, 100 | M_RST3 = 0xD3, 101 | M_RST4 = 0xD4, 102 | M_RST5 = 0xD5, 103 | M_RST6 = 0xD6, 104 | M_RST7 = 0xD7, 105 | 106 | M_SOI = 0xD8, 107 | M_EOI = 0xD9, 108 | M_SOS = 0xDA, 109 | M_DQT = 0xDB, 110 | M_DNL = 0xDC, 111 | M_DRI = 0xDD, 112 | M_DHP = 0xDE, 113 | M_EXP = 0xDF, 114 | 115 | M_APP0 = 0xE0, 116 | M_APP15 = 0xEF, 117 | 118 | M_JPG0 = 0xF0, 119 | M_JPG13 = 0xFD, 120 | M_COM = 0xFE, 121 | 122 | M_TEM = 0x01, 123 | 124 | M_ERROR = 0x100, 125 | 126 | RST0 = 0xD0 127 | } JPEG_MARKER; 128 | //------------------------------------------------------------------------------ 129 | static const int8 ZAG[] = 130 | { 131 | 0, 1, 8, 16, 9, 2, 3, 10, 132 | 17, 24, 32, 25, 18, 11, 4, 5, 133 | 12, 19, 26, 33, 40, 48, 41, 34, 134 | 27, 20, 13, 6, 7, 14, 21, 28, 135 | 35, 42, 49, 56, 57, 50, 43, 36, 136 | 29, 22, 15, 23, 30, 37, 44, 51, 137 | 58, 59, 52, 45, 38, 31, 39, 46, 138 | 53, 60, 61, 54, 47, 55, 62, 63, 139 | }; 140 | //------------------------------------------------------------------------------ 141 | // 128 bytes 142 | static int16 gCoeffBuf[8*8]; 143 | 144 | // 8*8*4 bytes * 3 = 768 145 | static uint8 gMCUBufR[256]; 146 | static uint8 gMCUBufG[256]; 147 | static uint8 gMCUBufB[256]; 148 | 149 | // 256 bytes 150 | static int16 gQuant0[8*8]; 151 | static int16 gQuant1[8*8]; 152 | 153 | // 6 bytes 154 | static int16 gLastDC[3]; 155 | 156 | typedef struct HuffTableT 157 | { 158 | uint16 mMinCode[16]; 159 | uint16 mMaxCode[16]; 160 | uint8 mValPtr[16]; 161 | } HuffTable; 162 | 163 | // DC - 192 164 | static HuffTable gHuffTab0; 165 | 166 | static uint8 gHuffVal0[16]; 167 | 168 | static HuffTable gHuffTab1; 169 | static uint8 gHuffVal1[16]; 170 | 171 | // AC - 672 172 | static HuffTable gHuffTab2; 173 | static uint8 gHuffVal2[256]; 174 | 175 | static HuffTable gHuffTab3; 176 | static uint8 gHuffVal3[256]; 177 | 178 | static uint8 gValidHuffTables; 179 | static uint8 gValidQuantTables; 180 | 181 | static uint8 gTemFlag; 182 | #define PJPG_MAX_IN_BUF_SIZE 256 183 | static uint8 gInBuf[PJPG_MAX_IN_BUF_SIZE]; 184 | static uint8 gInBufOfs; 185 | static uint8 gInBufLeft; 186 | 187 | static uint16 gBitBuf; 188 | static uint8 gBitsLeft; 189 | //------------------------------------------------------------------------------ 190 | static uint16 gImageXSize; 191 | static uint16 gImageYSize; 192 | static uint8 gCompsInFrame; 193 | static uint8 gCompIdent[3]; 194 | static uint8 gCompHSamp[3]; 195 | static uint8 gCompVSamp[3]; 196 | static uint8 gCompQuant[3]; 197 | 198 | static uint16 gRestartInterval; 199 | static uint16 gNextRestartNum; 200 | static uint16 gRestartsLeft; 201 | 202 | static uint8 gCompsInScan; 203 | static uint8 gCompList[3]; 204 | static uint8 gCompDCTab[3]; // 0,1 205 | static uint8 gCompACTab[3]; // 0,1 206 | 207 | static pjpeg_scan_type_t gScanType; 208 | 209 | static uint8 gMaxBlocksPerMCU; 210 | static uint8 gMaxMCUXSize; 211 | static uint8 gMaxMCUYSize; 212 | static uint16 gMaxMCUSPerRow; 213 | static uint16 gMaxMCUSPerCol; 214 | 215 | static uint16 gNumMCUSRemainingX, gNumMCUSRemainingY; 216 | 217 | static uint8 gMCUOrg[6]; 218 | 219 | static pjpeg_need_bytes_callback_t g_pNeedBytesCallback; 220 | static void *g_pCallback_data; 221 | static uint8 gCallbackStatus; 222 | static uint8 gReduce; 223 | //------------------------------------------------------------------------------ 224 | static void fillInBuf(void) 225 | { 226 | unsigned char status; 227 | 228 | // Reserve a few bytes at the beginning of the buffer for putting back ("stuffing") chars. 229 | gInBufOfs = 4; 230 | gInBufLeft = 0; 231 | 232 | status = (*g_pNeedBytesCallback)(gInBuf + gInBufOfs, PJPG_MAX_IN_BUF_SIZE - gInBufOfs, &gInBufLeft, g_pCallback_data); 233 | if (status) 234 | { 235 | // The user provided need bytes callback has indicated an error, so record the error and continue trying to decode. 236 | // The highest level pjpeg entrypoints will catch the error and return the non-zero status. 237 | gCallbackStatus = status; 238 | } 239 | } 240 | //------------------------------------------------------------------------------ 241 | static PJPG_INLINE uint8 getChar(void) 242 | { 243 | if (!gInBufLeft) 244 | { 245 | fillInBuf(); 246 | if (!gInBufLeft) 247 | { 248 | gTemFlag = ~gTemFlag; 249 | return gTemFlag ? 0xFF : 0xD9; 250 | } 251 | } 252 | 253 | gInBufLeft--; 254 | return gInBuf[gInBufOfs++]; 255 | } 256 | //------------------------------------------------------------------------------ 257 | static PJPG_INLINE void stuffChar(uint8 i) 258 | { 259 | gInBufOfs--; 260 | gInBuf[gInBufOfs] = i; 261 | gInBufLeft++; 262 | } 263 | //------------------------------------------------------------------------------ 264 | static PJPG_INLINE uint8 getOctet(uint8 FFCheck) 265 | { 266 | uint8 c = getChar(); 267 | 268 | if ((FFCheck) && (c == 0xFF)) 269 | { 270 | uint8 n = getChar(); 271 | 272 | if (n) 273 | { 274 | stuffChar(n); 275 | stuffChar(0xFF); 276 | } 277 | } 278 | 279 | return c; 280 | } 281 | //------------------------------------------------------------------------------ 282 | static uint16 getBits(uint8 numBits, uint8 FFCheck) 283 | { 284 | uint8 origBits = numBits; 285 | uint16 ret = gBitBuf; 286 | 287 | if (numBits > 8) 288 | { 289 | numBits -= 8; 290 | 291 | gBitBuf <<= gBitsLeft; 292 | 293 | gBitBuf |= getOctet(FFCheck); 294 | 295 | gBitBuf <<= (8 - gBitsLeft); 296 | 297 | ret = (ret & 0xFF00) | (gBitBuf >> 8); 298 | } 299 | 300 | if (gBitsLeft < numBits) 301 | { 302 | gBitBuf <<= gBitsLeft; 303 | 304 | gBitBuf |= getOctet(FFCheck); 305 | 306 | gBitBuf <<= (numBits - gBitsLeft); 307 | 308 | gBitsLeft = 8 - (numBits - gBitsLeft); 309 | } 310 | else 311 | { 312 | gBitsLeft = (uint8)(gBitsLeft - numBits); 313 | gBitBuf <<= numBits; 314 | } 315 | 316 | return ret >> (16 - origBits); 317 | } 318 | //------------------------------------------------------------------------------ 319 | static PJPG_INLINE uint16 getBits1(uint8 numBits) 320 | { 321 | return getBits(numBits, 0); 322 | } 323 | //------------------------------------------------------------------------------ 324 | static PJPG_INLINE uint16 getBits2(uint8 numBits) 325 | { 326 | return getBits(numBits, 1); 327 | } 328 | //------------------------------------------------------------------------------ 329 | static PJPG_INLINE uint8 getBit(void) 330 | { 331 | uint8 ret = 0; 332 | if (gBitBuf & 0x8000) 333 | ret = 1; 334 | 335 | if (!gBitsLeft) 336 | { 337 | gBitBuf |= getOctet(1); 338 | 339 | gBitsLeft += 8; 340 | } 341 | 342 | gBitsLeft--; 343 | gBitBuf <<= 1; 344 | 345 | return ret; 346 | } 347 | //------------------------------------------------------------------------------ 348 | static uint16 getExtendTest(uint8 i) 349 | { 350 | switch (i) 351 | { 352 | case 0: return 0; 353 | case 1: return 0x0001; 354 | case 2: return 0x0002; 355 | case 3: return 0x0004; 356 | case 4: return 0x0008; 357 | case 5: return 0x0010; 358 | case 6: return 0x0020; 359 | case 7: return 0x0040; 360 | case 8: return 0x0080; 361 | case 9: return 0x0100; 362 | case 10: return 0x0200; 363 | case 11: return 0x0400; 364 | case 12: return 0x0800; 365 | case 13: return 0x1000; 366 | case 14: return 0x2000; 367 | case 15: return 0x4000; 368 | default: return 0; 369 | } 370 | } 371 | //------------------------------------------------------------------------------ 372 | static int16 getExtendOffset(uint8 i) 373 | { 374 | switch (i) 375 | { 376 | case 0: return 0; 377 | case 1: return ((-1)<<1) + 1; 378 | case 2: return ((-1)<<2) + 1; 379 | case 3: return ((-1)<<3) + 1; 380 | case 4: return ((-1)<<4) + 1; 381 | case 5: return ((-1)<<5) + 1; 382 | case 6: return ((-1)<<6) + 1; 383 | case 7: return ((-1)<<7) + 1; 384 | case 8: return ((-1)<<8) + 1; 385 | case 9: return ((-1)<<9) + 1; 386 | case 10: return ((-1)<<10) + 1; 387 | case 11: return ((-1)<<11) + 1; 388 | case 12: return ((-1)<<12) + 1; 389 | case 13: return ((-1)<<13) + 1; 390 | case 14: return ((-1)<<14) + 1; 391 | case 15: return ((-1)<<15) + 1; 392 | default: return 0; 393 | } 394 | }; 395 | //------------------------------------------------------------------------------ 396 | static PJPG_INLINE int16 huffExtend(uint16 x, uint8 s) 397 | { 398 | return ((x < getExtendTest(s)) ? ((int16)x + getExtendOffset(s)) : (int16)x); 399 | } 400 | //------------------------------------------------------------------------------ 401 | static PJPG_INLINE uint8 huffDecode(const HuffTable* pHuffTable, const uint8* pHuffVal) 402 | { 403 | uint8 i = 0; 404 | uint8 j; 405 | uint16 code = getBit(); 406 | 407 | // This func only reads a bit at a time, which on modern CPU's is not terribly efficient. 408 | // But on microcontrollers without strong integer shifting support this seems like a 409 | // more reasonable approach. 410 | for ( ; ; ) 411 | { 412 | uint16 maxCode; 413 | 414 | if (i == 16) 415 | return 0; 416 | 417 | maxCode = pHuffTable->mMaxCode[i]; 418 | if ((code <= maxCode) && (maxCode != 0xFFFF)) 419 | break; 420 | 421 | i++; 422 | code <<= 1; 423 | code |= getBit(); 424 | } 425 | 426 | j = pHuffTable->mValPtr[i]; 427 | j = (uint8)(j + (code - pHuffTable->mMinCode[i])); 428 | 429 | return pHuffVal[j]; 430 | } 431 | //------------------------------------------------------------------------------ 432 | static void huffCreate(const uint8* pBits, HuffTable* pHuffTable) 433 | { 434 | uint8 i = 0; 435 | uint8 j = 0; 436 | 437 | uint16 code = 0; 438 | 439 | for ( ; ; ) 440 | { 441 | uint8 num = pBits[i]; 442 | 443 | if (!num) 444 | { 445 | pHuffTable->mMinCode[i] = 0x0000; 446 | pHuffTable->mMaxCode[i] = 0xFFFF; 447 | pHuffTable->mValPtr[i] = 0; 448 | } 449 | else 450 | { 451 | pHuffTable->mMinCode[i] = code; 452 | pHuffTable->mMaxCode[i] = code + num - 1; 453 | pHuffTable->mValPtr[i] = j; 454 | 455 | j = (uint8)(j + num); 456 | 457 | code = (uint16)(code + num); 458 | } 459 | 460 | code <<= 1; 461 | 462 | i++; 463 | if (i > 15) 464 | break; 465 | } 466 | } 467 | //------------------------------------------------------------------------------ 468 | static HuffTable* getHuffTable(uint8 index) 469 | { 470 | // 0-1 = DC 471 | // 2-3 = AC 472 | switch (index) 473 | { 474 | case 0: return &gHuffTab0; 475 | case 1: return &gHuffTab1; 476 | case 2: return &gHuffTab2; 477 | case 3: return &gHuffTab3; 478 | default: return 0; 479 | } 480 | } 481 | //------------------------------------------------------------------------------ 482 | static uint8* getHuffVal(uint8 index) 483 | { 484 | // 0-1 = DC 485 | // 2-3 = AC 486 | switch (index) 487 | { 488 | case 0: return gHuffVal0; 489 | case 1: return gHuffVal1; 490 | case 2: return gHuffVal2; 491 | case 3: return gHuffVal3; 492 | default: return 0; 493 | } 494 | } 495 | //------------------------------------------------------------------------------ 496 | static uint16 getMaxHuffCodes(uint8 index) 497 | { 498 | return (index < 2) ? 12 : 255; 499 | } 500 | //------------------------------------------------------------------------------ 501 | static uint8 readDHTMarker(void) 502 | { 503 | uint8 bits[16]; 504 | uint16 left = getBits1(16); 505 | 506 | if (left < 2) 507 | return PJPG_BAD_DHT_MARKER; 508 | 509 | left -= 2; 510 | 511 | while (left) 512 | { 513 | uint8 i, tableIndex, index; 514 | uint8* pHuffVal; 515 | HuffTable* pHuffTable; 516 | uint16 count, totalRead; 517 | 518 | index = (uint8)getBits1(8); 519 | 520 | if ( ((index & 0xF) > 1) || ((index & 0xF0) > 0x10) ) 521 | return PJPG_BAD_DHT_INDEX; 522 | 523 | tableIndex = ((index >> 3) & 2) + (index & 1); 524 | 525 | pHuffTable = getHuffTable(tableIndex); 526 | pHuffVal = getHuffVal(tableIndex); 527 | 528 | gValidHuffTables |= (1 << tableIndex); 529 | 530 | count = 0; 531 | for (i = 0; i <= 15; i++) 532 | { 533 | uint8 n = (uint8)getBits1(8); 534 | bits[i] = n; 535 | count = (uint16)(count + n); 536 | } 537 | 538 | if (count > getMaxHuffCodes(tableIndex)) 539 | return PJPG_BAD_DHT_COUNTS; 540 | 541 | for (i = 0; i < count; i++) 542 | pHuffVal[i] = (uint8)getBits1(8); 543 | 544 | totalRead = 1 + 16 + count; 545 | 546 | if (left < totalRead) 547 | return PJPG_BAD_DHT_MARKER; 548 | 549 | left = (uint16)(left - totalRead); 550 | 551 | huffCreate(bits, pHuffTable); 552 | } 553 | 554 | return 0; 555 | } 556 | //------------------------------------------------------------------------------ 557 | static void createWinogradQuant(int16* pQuant); 558 | 559 | static uint8 readDQTMarker(void) 560 | { 561 | uint16 left = getBits1(16); 562 | 563 | if (left < 2) 564 | return PJPG_BAD_DQT_MARKER; 565 | 566 | left -= 2; 567 | 568 | while (left) 569 | { 570 | uint8 i; 571 | uint8 n = (uint8)getBits1(8); 572 | uint8 prec = n >> 4; 573 | uint16 totalRead; 574 | 575 | n &= 0x0F; 576 | 577 | if (n > 1) 578 | return PJPG_BAD_DQT_TABLE; 579 | 580 | gValidQuantTables |= (n ? 2 : 1); 581 | 582 | // read quantization entries, in zag order 583 | for (i = 0; i < 64; i++) 584 | { 585 | uint16 temp = getBits1(8); 586 | 587 | if (prec) 588 | temp = (temp << 8) + getBits1(8); 589 | 590 | if (n) 591 | gQuant1[i] = (int16)temp; 592 | else 593 | gQuant0[i] = (int16)temp; 594 | } 595 | 596 | createWinogradQuant(n ? gQuant1 : gQuant0); 597 | 598 | totalRead = 64 + 1; 599 | 600 | if (prec) 601 | totalRead += 64; 602 | 603 | if (left < totalRead) 604 | return PJPG_BAD_DQT_LENGTH; 605 | 606 | left = (uint16)(left - totalRead); 607 | } 608 | 609 | return 0; 610 | } 611 | //------------------------------------------------------------------------------ 612 | static uint8 readSOFMarker(void) 613 | { 614 | uint8 i; 615 | uint16 left = getBits1(16); 616 | 617 | if (getBits1(8) != 8) 618 | return PJPG_BAD_PRECISION; 619 | 620 | gImageYSize = getBits1(16); 621 | 622 | if ((!gImageYSize) || (gImageYSize > PJPG_MAX_HEIGHT)) 623 | return PJPG_BAD_HEIGHT; 624 | 625 | gImageXSize = getBits1(16); 626 | 627 | if ((!gImageXSize) || (gImageXSize > PJPG_MAX_WIDTH)) 628 | return PJPG_BAD_WIDTH; 629 | 630 | gCompsInFrame = (uint8)getBits1(8); 631 | 632 | if (gCompsInFrame > 3) 633 | return PJPG_TOO_MANY_COMPONENTS; 634 | 635 | if (left != (gCompsInFrame + gCompsInFrame + gCompsInFrame + 8)) 636 | return PJPG_BAD_SOF_LENGTH; 637 | 638 | for (i = 0; i < gCompsInFrame; i++) 639 | { 640 | gCompIdent[i] = (uint8)getBits1(8); 641 | gCompHSamp[i] = (uint8)getBits1(4); 642 | gCompVSamp[i] = (uint8)getBits1(4); 643 | gCompQuant[i] = (uint8)getBits1(8); 644 | 645 | if (gCompQuant[i] > 1) 646 | return PJPG_UNSUPPORTED_QUANT_TABLE; 647 | } 648 | 649 | return 0; 650 | } 651 | //------------------------------------------------------------------------------ 652 | // Used to skip unrecognized markers. 653 | static uint8 skipVariableMarker(void) 654 | { 655 | uint16 left = getBits1(16); 656 | 657 | if (left < 2) 658 | return PJPG_BAD_VARIABLE_MARKER; 659 | 660 | left -= 2; 661 | 662 | while (left) 663 | { 664 | getBits1(8); 665 | left--; 666 | } 667 | 668 | return 0; 669 | } 670 | //------------------------------------------------------------------------------ 671 | // Read a define restart interval (DRI) marker. 672 | static uint8 readDRIMarker(void) 673 | { 674 | if (getBits1(16) != 4) 675 | return PJPG_BAD_DRI_LENGTH; 676 | 677 | gRestartInterval = getBits1(16); 678 | 679 | return 0; 680 | } 681 | //------------------------------------------------------------------------------ 682 | // Read a start of scan (SOS) marker. 683 | static uint8 readSOSMarker(void) 684 | { 685 | uint8 i; 686 | uint16 left = getBits1(16); 687 | uint8 spectral_start, spectral_end, successive_high, successive_low; 688 | 689 | gCompsInScan = (uint8)getBits1(8); 690 | 691 | left -= 3; 692 | 693 | if ( (left != (gCompsInScan + gCompsInScan + 3)) || (gCompsInScan < 1) || (gCompsInScan > PJPG_MAXCOMPSINSCAN) ) 694 | return PJPG_BAD_SOS_LENGTH; 695 | 696 | for (i = 0; i < gCompsInScan; i++) 697 | { 698 | uint8 cc = (uint8)getBits1(8); 699 | uint8 c = (uint8)getBits1(8); 700 | uint8 ci; 701 | 702 | left -= 2; 703 | 704 | for (ci = 0; ci < gCompsInFrame; ci++) 705 | if (cc == gCompIdent[ci]) 706 | break; 707 | 708 | if (ci >= gCompsInFrame) 709 | return PJPG_BAD_SOS_COMP_ID; 710 | 711 | gCompList[i] = ci; 712 | gCompDCTab[ci] = (c >> 4) & 15; 713 | gCompACTab[ci] = (c & 15); 714 | } 715 | 716 | spectral_start = (uint8)getBits1(8); 717 | spectral_end = (uint8)getBits1(8); 718 | successive_high = (uint8)getBits1(4); 719 | successive_low = (uint8)getBits1(4); 720 | 721 | left -= 3; 722 | 723 | while (left) 724 | { 725 | getBits1(8); 726 | left--; 727 | } 728 | 729 | return 0; 730 | } 731 | //------------------------------------------------------------------------------ 732 | static uint8 nextMarker(void) 733 | { 734 | uint8 c; 735 | uint8 bytes = 0; 736 | 737 | do 738 | { 739 | do 740 | { 741 | bytes++; 742 | 743 | c = (uint8)getBits1(8); 744 | 745 | } while (c != 0xFF); 746 | 747 | do 748 | { 749 | c = (uint8)getBits1(8); 750 | 751 | } while (c == 0xFF); 752 | 753 | } while (c == 0); 754 | 755 | // If bytes > 0 here, there where extra bytes before the marker (not good). 756 | 757 | return c; 758 | } 759 | //------------------------------------------------------------------------------ 760 | // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is 761 | // encountered. 762 | static uint8 processMarkers(uint8* pMarker) 763 | { 764 | for ( ; ; ) 765 | { 766 | uint8 c = nextMarker(); 767 | 768 | switch (c) 769 | { 770 | case M_SOF0: 771 | case M_SOF1: 772 | case M_SOF2: 773 | case M_SOF3: 774 | case M_SOF5: 775 | case M_SOF6: 776 | case M_SOF7: 777 | // case M_JPG: 778 | case M_SOF9: 779 | case M_SOF10: 780 | case M_SOF11: 781 | case M_SOF13: 782 | case M_SOF14: 783 | case M_SOF15: 784 | case M_SOI: 785 | case M_EOI: 786 | case M_SOS: 787 | { 788 | *pMarker = c; 789 | return 0; 790 | } 791 | case M_DHT: 792 | { 793 | readDHTMarker(); 794 | break; 795 | } 796 | // Sorry, no arithmetic support at this time. Dumb patents! 797 | case M_DAC: 798 | { 799 | return PJPG_NO_ARITHMITIC_SUPPORT; 800 | } 801 | case M_DQT: 802 | { 803 | readDQTMarker(); 804 | break; 805 | } 806 | case M_DRI: 807 | { 808 | readDRIMarker(); 809 | break; 810 | } 811 | //case M_APP0: /* no need to read the JFIF marker */ 812 | 813 | case M_JPG: 814 | case M_RST0: /* no parameters */ 815 | case M_RST1: 816 | case M_RST2: 817 | case M_RST3: 818 | case M_RST4: 819 | case M_RST5: 820 | case M_RST6: 821 | case M_RST7: 822 | case M_TEM: 823 | { 824 | return PJPG_UNEXPECTED_MARKER; 825 | } 826 | default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ 827 | { 828 | skipVariableMarker(); 829 | break; 830 | } 831 | } 832 | } 833 | // return 0; 834 | } 835 | //------------------------------------------------------------------------------ 836 | // Finds the start of image (SOI) marker. 837 | static uint8 locateSOIMarker(void) 838 | { 839 | uint16 bytesleft; 840 | 841 | uint8 lastchar = (uint8)getBits1(8); 842 | 843 | uint8 thischar = (uint8)getBits1(8); 844 | 845 | /* ok if it's a normal JPEG file without a special header */ 846 | 847 | if ((lastchar == 0xFF) && (thischar == M_SOI)) 848 | return 0; 849 | 850 | bytesleft = 4096; //512; 851 | 852 | for ( ; ; ) 853 | { 854 | if (--bytesleft == 0) 855 | return PJPG_NOT_JPEG; 856 | 857 | lastchar = thischar; 858 | 859 | thischar = (uint8)getBits1(8); 860 | 861 | if (lastchar == 0xFF) 862 | { 863 | if (thischar == M_SOI) 864 | break; 865 | else if (thischar == M_EOI) //getBits1 will keep returning M_EOI if we read past the end 866 | return PJPG_NOT_JPEG; 867 | } 868 | } 869 | 870 | /* Check the next character after marker: if it's not 0xFF, it can't 871 | be the start of the next marker, so the file is bad */ 872 | 873 | thischar = (uint8)((gBitBuf >> 8) & 0xFF); 874 | 875 | if (thischar != 0xFF) 876 | return PJPG_NOT_JPEG; 877 | 878 | return 0; 879 | } 880 | //------------------------------------------------------------------------------ 881 | // Find a start of frame (SOF) marker. 882 | static uint8 locateSOFMarker(void) 883 | { 884 | uint8 c; 885 | 886 | uint8 status = locateSOIMarker(); 887 | if (status) 888 | return status; 889 | 890 | status = processMarkers(&c); 891 | if (status) 892 | return status; 893 | 894 | switch (c) 895 | { 896 | case M_SOF2: 897 | { 898 | // Progressive JPEG - not supported by picojpeg (would require too 899 | // much memory, or too many IDCT's for embedded systems). 900 | return PJPG_UNSUPPORTED_MODE; 901 | } 902 | case M_SOF0: /* baseline DCT */ 903 | { 904 | status = readSOFMarker(); 905 | if (status) 906 | return status; 907 | 908 | break; 909 | } 910 | case M_SOF9: 911 | { 912 | return PJPG_NO_ARITHMITIC_SUPPORT; 913 | } 914 | case M_SOF1: /* extended sequential DCT */ 915 | default: 916 | { 917 | return PJPG_UNSUPPORTED_MARKER; 918 | } 919 | } 920 | 921 | return 0; 922 | } 923 | //------------------------------------------------------------------------------ 924 | // Find a start of scan (SOS) marker. 925 | static uint8 locateSOSMarker(uint8* pFoundEOI) 926 | { 927 | uint8 c; 928 | uint8 status; 929 | 930 | *pFoundEOI = 0; 931 | 932 | status = processMarkers(&c); 933 | if (status) 934 | return status; 935 | 936 | if (c == M_EOI) 937 | { 938 | *pFoundEOI = 1; 939 | return 0; 940 | } 941 | else if (c != M_SOS) 942 | return PJPG_UNEXPECTED_MARKER; 943 | 944 | return readSOSMarker(); 945 | } 946 | //------------------------------------------------------------------------------ 947 | static uint8 init(void) 948 | { 949 | gImageXSize = 0; 950 | gImageYSize = 0; 951 | gCompsInFrame = 0; 952 | gRestartInterval = 0; 953 | gCompsInScan = 0; 954 | gValidHuffTables = 0; 955 | gValidQuantTables = 0; 956 | gTemFlag = 0; 957 | gInBufOfs = 0; 958 | gInBufLeft = 0; 959 | gBitBuf = 0; 960 | gBitsLeft = 8; 961 | 962 | getBits1(8); 963 | getBits1(8); 964 | 965 | return 0; 966 | } 967 | //------------------------------------------------------------------------------ 968 | // This method throws back into the stream any bytes that where read 969 | // into the bit buffer during initial marker scanning. 970 | static void fixInBuffer(void) 971 | { 972 | /* In case any 0xFF's where pulled into the buffer during marker scanning */ 973 | 974 | if (gBitsLeft > 0) 975 | stuffChar((uint8)gBitBuf); 976 | 977 | stuffChar((uint8)(gBitBuf >> 8)); 978 | 979 | gBitsLeft = 8; 980 | getBits2(8); 981 | getBits2(8); 982 | } 983 | //------------------------------------------------------------------------------ 984 | // Restart interval processing. 985 | static uint8 processRestart(void) 986 | { 987 | // Let's scan a little bit to find the marker, but not _too_ far. 988 | // 1536 is a "fudge factor" that determines how much to scan. 989 | uint16 i; 990 | uint8 c = 0; 991 | 992 | for (i = 1536; i > 0; i--) 993 | if (getChar() == 0xFF) 994 | break; 995 | 996 | if (i == 0) 997 | return PJPG_BAD_RESTART_MARKER; 998 | 999 | for ( ; i > 0; i--) 1000 | if ((c = getChar()) != 0xFF) 1001 | break; 1002 | 1003 | if (i == 0) 1004 | return PJPG_BAD_RESTART_MARKER; 1005 | 1006 | // Is it the expected marker? If not, something bad happened. 1007 | if (c != (gNextRestartNum + M_RST0)) 1008 | return PJPG_BAD_RESTART_MARKER; 1009 | 1010 | // Reset each component's DC prediction values. 1011 | gLastDC[0] = 0; 1012 | gLastDC[1] = 0; 1013 | gLastDC[2] = 0; 1014 | 1015 | gRestartsLeft = gRestartInterval; 1016 | 1017 | gNextRestartNum = (gNextRestartNum + 1) & 7; 1018 | 1019 | // Get the bit buffer going again 1020 | 1021 | gBitsLeft = 8; 1022 | getBits2(8); 1023 | getBits2(8); 1024 | 1025 | return 0; 1026 | } 1027 | //------------------------------------------------------------------------------ 1028 | // FIXME: findEOI() is not actually called at the end of the image 1029 | // (it's optional, and probably not needed on embedded devices) 1030 | static uint8 findEOI(void) 1031 | { 1032 | uint8 c; 1033 | uint8 status; 1034 | 1035 | // Prime the bit buffer 1036 | gBitsLeft = 8; 1037 | getBits1(8); 1038 | getBits1(8); 1039 | 1040 | // The next marker _should_ be EOI 1041 | status = processMarkers(&c); 1042 | if (status) 1043 | return status; 1044 | else if (gCallbackStatus) 1045 | return gCallbackStatus; 1046 | 1047 | //gTotalBytesRead -= in_buf_left; 1048 | if (c != M_EOI) 1049 | return PJPG_UNEXPECTED_MARKER; 1050 | 1051 | return 0; 1052 | } 1053 | //------------------------------------------------------------------------------ 1054 | static uint8 checkHuffTables(void) 1055 | { 1056 | uint8 i; 1057 | 1058 | for (i = 0; i < gCompsInScan; i++) 1059 | { 1060 | uint8 compDCTab = gCompDCTab[gCompList[i]]; 1061 | uint8 compACTab = gCompACTab[gCompList[i]] + 2; 1062 | 1063 | if ( ((gValidHuffTables & (1 << compDCTab)) == 0) || 1064 | ((gValidHuffTables & (1 << compACTab)) == 0) ) 1065 | return PJPG_UNDEFINED_HUFF_TABLE; 1066 | } 1067 | 1068 | return 0; 1069 | } 1070 | //------------------------------------------------------------------------------ 1071 | static uint8 checkQuantTables(void) 1072 | { 1073 | uint8 i; 1074 | 1075 | for (i = 0; i < gCompsInScan; i++) 1076 | { 1077 | uint8 compQuantMask = gCompQuant[gCompList[i]] ? 2 : 1; 1078 | 1079 | if ((gValidQuantTables & compQuantMask) == 0) 1080 | return PJPG_UNDEFINED_QUANT_TABLE; 1081 | } 1082 | 1083 | return 0; 1084 | } 1085 | //------------------------------------------------------------------------------ 1086 | static uint8 initScan(void) 1087 | { 1088 | uint8 foundEOI; 1089 | uint8 status = locateSOSMarker(&foundEOI); 1090 | if (status) 1091 | return status; 1092 | if (foundEOI) 1093 | return PJPG_UNEXPECTED_MARKER; 1094 | 1095 | status = checkHuffTables(); 1096 | if (status) 1097 | return status; 1098 | 1099 | status = checkQuantTables(); 1100 | if (status) 1101 | return status; 1102 | 1103 | gLastDC[0] = 0; 1104 | gLastDC[1] = 0; 1105 | gLastDC[2] = 0; 1106 | 1107 | if (gRestartInterval) 1108 | { 1109 | gRestartsLeft = gRestartInterval; 1110 | gNextRestartNum = 0; 1111 | } 1112 | 1113 | fixInBuffer(); 1114 | 1115 | return 0; 1116 | } 1117 | //------------------------------------------------------------------------------ 1118 | static uint8 initFrame(void) 1119 | { 1120 | if (gCompsInFrame == 1) 1121 | { 1122 | if ((gCompHSamp[0] != 1) || (gCompVSamp[0] != 1)) 1123 | return PJPG_UNSUPPORTED_SAMP_FACTORS; 1124 | 1125 | gScanType = PJPG_GRAYSCALE; 1126 | 1127 | gMaxBlocksPerMCU = 1; 1128 | gMCUOrg[0] = 0; 1129 | 1130 | gMaxMCUXSize = 8; 1131 | gMaxMCUYSize = 8; 1132 | } 1133 | else if (gCompsInFrame == 3) 1134 | { 1135 | if ( ((gCompHSamp[1] != 1) || (gCompVSamp[1] != 1)) || 1136 | ((gCompHSamp[2] != 1) || (gCompVSamp[2] != 1)) ) 1137 | return PJPG_UNSUPPORTED_SAMP_FACTORS; 1138 | 1139 | if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 1)) 1140 | { 1141 | gScanType = PJPG_YH1V1; 1142 | 1143 | gMaxBlocksPerMCU = 3; 1144 | gMCUOrg[0] = 0; 1145 | gMCUOrg[1] = 1; 1146 | gMCUOrg[2] = 2; 1147 | 1148 | gMaxMCUXSize = 8; 1149 | gMaxMCUYSize = 8; 1150 | } 1151 | else if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 2)) 1152 | { 1153 | gScanType = PJPG_YH1V2; 1154 | 1155 | gMaxBlocksPerMCU = 4; 1156 | gMCUOrg[0] = 0; 1157 | gMCUOrg[1] = 0; 1158 | gMCUOrg[2] = 1; 1159 | gMCUOrg[3] = 2; 1160 | 1161 | gMaxMCUXSize = 8; 1162 | gMaxMCUYSize = 16; 1163 | } 1164 | else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 1)) 1165 | { 1166 | gScanType = PJPG_YH2V1; 1167 | 1168 | gMaxBlocksPerMCU = 4; 1169 | gMCUOrg[0] = 0; 1170 | gMCUOrg[1] = 0; 1171 | gMCUOrg[2] = 1; 1172 | gMCUOrg[3] = 2; 1173 | 1174 | gMaxMCUXSize = 16; 1175 | gMaxMCUYSize = 8; 1176 | } 1177 | else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 2)) 1178 | { 1179 | gScanType = PJPG_YH2V2; 1180 | 1181 | gMaxBlocksPerMCU = 6; 1182 | gMCUOrg[0] = 0; 1183 | gMCUOrg[1] = 0; 1184 | gMCUOrg[2] = 0; 1185 | gMCUOrg[3] = 0; 1186 | gMCUOrg[4] = 1; 1187 | gMCUOrg[5] = 2; 1188 | 1189 | gMaxMCUXSize = 16; 1190 | gMaxMCUYSize = 16; 1191 | } 1192 | else 1193 | return PJPG_UNSUPPORTED_SAMP_FACTORS; 1194 | } 1195 | else 1196 | return PJPG_UNSUPPORTED_COLORSPACE; 1197 | 1198 | gMaxMCUSPerRow = (gImageXSize + (gMaxMCUXSize - 1)) >> ((gMaxMCUXSize == 8) ? 3 : 4); 1199 | gMaxMCUSPerCol = (gImageYSize + (gMaxMCUYSize - 1)) >> ((gMaxMCUYSize == 8) ? 3 : 4); 1200 | 1201 | // This can overflow on large JPEG's. 1202 | //gNumMCUSRemaining = gMaxMCUSPerRow * gMaxMCUSPerCol; 1203 | gNumMCUSRemainingX = gMaxMCUSPerRow; 1204 | gNumMCUSRemainingY = gMaxMCUSPerCol; 1205 | 1206 | return 0; 1207 | } 1208 | //---------------------------------------------------------------------------- 1209 | // Winograd IDCT: 5 multiplies per row/col, up to 80 muls for the 2D IDCT 1210 | 1211 | #define PJPG_DCT_SCALE_BITS 7 1212 | 1213 | #define PJPG_DCT_SCALE (1U << PJPG_DCT_SCALE_BITS) 1214 | 1215 | #define PJPG_DESCALE(x) PJPG_ARITH_SHIFT_RIGHT_N_16(((x) + (1 << (PJPG_DCT_SCALE_BITS - 1))), PJPG_DCT_SCALE_BITS) 1216 | 1217 | #define PJPG_WFIX(x) ((x) * PJPG_DCT_SCALE + 0.5f) 1218 | 1219 | #define PJPG_WINOGRAD_QUANT_SCALE_BITS 10 1220 | 1221 | const uint8 gWinogradQuant[] = 1222 | { 1223 | 128, 178, 178, 167, 246, 167, 151, 232, 1224 | 232, 151, 128, 209, 219, 209, 128, 101, 1225 | 178, 197, 197, 178, 101, 69, 139, 167, 1226 | 177, 167, 139, 69, 35, 96, 131, 151, 1227 | 151, 131, 96, 35, 49, 91, 118, 128, 1228 | 118, 91, 49, 46, 81, 101, 101, 81, 1229 | 46, 42, 69, 79, 69, 42, 35, 54, 1230 | 54, 35, 28, 37, 28, 19, 19, 10, 1231 | }; 1232 | 1233 | // Multiply quantization matrix by the Winograd IDCT scale factors 1234 | static void createWinogradQuant(int16* pQuant) 1235 | { 1236 | uint8 i; 1237 | 1238 | for (i = 0; i < 64; i++) 1239 | { 1240 | long x = pQuant[i]; 1241 | x *= gWinogradQuant[i]; 1242 | pQuant[i] = (int16)((x + (1 << (PJPG_WINOGRAD_QUANT_SCALE_BITS - PJPG_DCT_SCALE_BITS - 1))) >> (PJPG_WINOGRAD_QUANT_SCALE_BITS - PJPG_DCT_SCALE_BITS)); 1243 | } 1244 | } 1245 | 1246 | // These multiply helper functions are the 4 types of signed multiplies needed by the Winograd IDCT. 1247 | // A smart C compiler will optimize them to use 16x8 = 24 bit muls, if not you may need to tweak 1248 | // these functions or drop to CPU specific inline assembly. 1249 | 1250 | // 1/cos(4*pi/16) 1251 | // 362, 256+106 1252 | static PJPG_INLINE int16 imul_b1_b3(int16 w) 1253 | { 1254 | long x = (w * 362L); 1255 | x += 128L; 1256 | return (int16)(PJPG_ARITH_SHIFT_RIGHT_8_L(x)); 1257 | } 1258 | 1259 | // 1/cos(6*pi/16) 1260 | // 669, 256+256+157 1261 | static PJPG_INLINE int16 imul_b2(int16 w) 1262 | { 1263 | long x = (w * 669L); 1264 | x += 128L; 1265 | return (int16)(PJPG_ARITH_SHIFT_RIGHT_8_L(x)); 1266 | } 1267 | 1268 | // 1/cos(2*pi/16) 1269 | // 277, 256+21 1270 | static PJPG_INLINE int16 imul_b4(int16 w) 1271 | { 1272 | long x = (w * 277L); 1273 | x += 128L; 1274 | return (int16)(PJPG_ARITH_SHIFT_RIGHT_8_L(x)); 1275 | } 1276 | 1277 | // 1/(cos(2*pi/16) + cos(6*pi/16)) 1278 | // 196, 196 1279 | static PJPG_INLINE int16 imul_b5(int16 w) 1280 | { 1281 | long x = (w * 196L); 1282 | x += 128L; 1283 | return (int16)(PJPG_ARITH_SHIFT_RIGHT_8_L(x)); 1284 | } 1285 | 1286 | static PJPG_INLINE uint8 clamp(int16 s) 1287 | { 1288 | if ((uint16)s > 255U) 1289 | { 1290 | if (s < 0) 1291 | return 0; 1292 | else if (s > 255) 1293 | return 255; 1294 | } 1295 | 1296 | return (uint8)s; 1297 | } 1298 | 1299 | static void idctRows(void) 1300 | { 1301 | uint8 i; 1302 | int16* pSrc = gCoeffBuf; 1303 | 1304 | for (i = 0; i < 8; i++) 1305 | { 1306 | if ((pSrc[1] | pSrc[2] | pSrc[3] | pSrc[4] | pSrc[5] | pSrc[6] | pSrc[7]) == 0) 1307 | { 1308 | // Short circuit the 1D IDCT if only the DC component is non-zero 1309 | int16 src0 = *pSrc; 1310 | 1311 | *(pSrc+1) = src0; 1312 | *(pSrc+2) = src0; 1313 | *(pSrc+3) = src0; 1314 | *(pSrc+4) = src0; 1315 | *(pSrc+5) = src0; 1316 | *(pSrc+6) = src0; 1317 | *(pSrc+7) = src0; 1318 | } 1319 | else 1320 | { 1321 | int16 src4 = *(pSrc+5); 1322 | int16 src7 = *(pSrc+3); 1323 | int16 x4 = src4 - src7; 1324 | int16 x7 = src4 + src7; 1325 | 1326 | int16 src5 = *(pSrc+1); 1327 | int16 src6 = *(pSrc+7); 1328 | int16 x5 = src5 + src6; 1329 | int16 x6 = src5 - src6; 1330 | 1331 | int16 tmp1 = imul_b5(x4 - x6); 1332 | int16 stg26 = imul_b4(x6) - tmp1; 1333 | 1334 | int16 x24 = tmp1 - imul_b2(x4); 1335 | 1336 | int16 x15 = x5 - x7; 1337 | int16 x17 = x5 + x7; 1338 | 1339 | int16 tmp2 = stg26 - x17; 1340 | int16 tmp3 = imul_b1_b3(x15) - tmp2; 1341 | int16 x44 = tmp3 + x24; 1342 | 1343 | int16 src0 = *(pSrc+0); 1344 | int16 src1 = *(pSrc+4); 1345 | int16 x30 = src0 + src1; 1346 | int16 x31 = src0 - src1; 1347 | 1348 | int16 src2 = *(pSrc+2); 1349 | int16 src3 = *(pSrc+6); 1350 | int16 x12 = src2 - src3; 1351 | int16 x13 = src2 + src3; 1352 | 1353 | int16 x32 = imul_b1_b3(x12) - x13; 1354 | 1355 | int16 x40 = x30 + x13; 1356 | int16 x43 = x30 - x13; 1357 | int16 x41 = x31 + x32; 1358 | int16 x42 = x31 - x32; 1359 | 1360 | *(pSrc+0) = x40 + x17; 1361 | *(pSrc+1) = x41 + tmp2; 1362 | *(pSrc+2) = x42 + tmp3; 1363 | *(pSrc+3) = x43 - x44; 1364 | *(pSrc+4) = x43 + x44; 1365 | *(pSrc+5) = x42 - tmp3; 1366 | *(pSrc+6) = x41 - tmp2; 1367 | *(pSrc+7) = x40 - x17; 1368 | } 1369 | 1370 | pSrc += 8; 1371 | } 1372 | } 1373 | 1374 | static void idctCols(void) 1375 | { 1376 | uint8 i; 1377 | 1378 | int16* pSrc = gCoeffBuf; 1379 | 1380 | for (i = 0; i < 8; i++) 1381 | { 1382 | if ((pSrc[1*8] | pSrc[2*8] | pSrc[3*8] | pSrc[4*8] | pSrc[5*8] | pSrc[6*8] | pSrc[7*8]) == 0) 1383 | { 1384 | // Short circuit the 1D IDCT if only the DC component is non-zero 1385 | uint8 c = clamp(PJPG_DESCALE(*pSrc) + 128); 1386 | *(pSrc+0*8) = c; 1387 | *(pSrc+1*8) = c; 1388 | *(pSrc+2*8) = c; 1389 | *(pSrc+3*8) = c; 1390 | *(pSrc+4*8) = c; 1391 | *(pSrc+5*8) = c; 1392 | *(pSrc+6*8) = c; 1393 | *(pSrc+7*8) = c; 1394 | } 1395 | else 1396 | { 1397 | int16 src4 = *(pSrc+5*8); 1398 | int16 src7 = *(pSrc+3*8); 1399 | int16 x4 = src4 - src7; 1400 | int16 x7 = src4 + src7; 1401 | 1402 | int16 src5 = *(pSrc+1*8); 1403 | int16 src6 = *(pSrc+7*8); 1404 | int16 x5 = src5 + src6; 1405 | int16 x6 = src5 - src6; 1406 | 1407 | int16 tmp1 = imul_b5(x4 - x6); 1408 | int16 stg26 = imul_b4(x6) - tmp1; 1409 | 1410 | int16 x24 = tmp1 - imul_b2(x4); 1411 | 1412 | int16 x15 = x5 - x7; 1413 | int16 x17 = x5 + x7; 1414 | 1415 | int16 tmp2 = stg26 - x17; 1416 | int16 tmp3 = imul_b1_b3(x15) - tmp2; 1417 | int16 x44 = tmp3 + x24; 1418 | 1419 | int16 src0 = *(pSrc+0*8); 1420 | int16 src1 = *(pSrc+4*8); 1421 | int16 x30 = src0 + src1; 1422 | int16 x31 = src0 - src1; 1423 | 1424 | int16 src2 = *(pSrc+2*8); 1425 | int16 src3 = *(pSrc+6*8); 1426 | int16 x12 = src2 - src3; 1427 | int16 x13 = src2 + src3; 1428 | 1429 | int16 x32 = imul_b1_b3(x12) - x13; 1430 | 1431 | int16 x40 = x30 + x13; 1432 | int16 x43 = x30 - x13; 1433 | int16 x41 = x31 + x32; 1434 | int16 x42 = x31 - x32; 1435 | 1436 | // descale, convert to unsigned and clamp to 8-bit 1437 | *(pSrc+0*8) = clamp(PJPG_DESCALE(x40 + x17) + 128); 1438 | *(pSrc+1*8) = clamp(PJPG_DESCALE(x41 + tmp2) + 128); 1439 | *(pSrc+2*8) = clamp(PJPG_DESCALE(x42 + tmp3) + 128); 1440 | *(pSrc+3*8) = clamp(PJPG_DESCALE(x43 - x44) + 128); 1441 | *(pSrc+4*8) = clamp(PJPG_DESCALE(x43 + x44) + 128); 1442 | *(pSrc+5*8) = clamp(PJPG_DESCALE(x42 - tmp3) + 128); 1443 | *(pSrc+6*8) = clamp(PJPG_DESCALE(x41 - tmp2) + 128); 1444 | *(pSrc+7*8) = clamp(PJPG_DESCALE(x40 - x17) + 128); 1445 | } 1446 | 1447 | pSrc++; 1448 | } 1449 | } 1450 | 1451 | /*----------------------------------------------------------------------------*/ 1452 | static PJPG_INLINE uint8 addAndClamp(uint8 a, int16 b) 1453 | { 1454 | b = a + b; 1455 | 1456 | if ((uint16)b > 255U) 1457 | { 1458 | if (b < 0) 1459 | return 0; 1460 | else if (b > 255) 1461 | return 255; 1462 | } 1463 | 1464 | return (uint8)b; 1465 | } 1466 | /*----------------------------------------------------------------------------*/ 1467 | static PJPG_INLINE uint8 subAndClamp(uint8 a, int16 b) 1468 | { 1469 | b = a - b; 1470 | 1471 | if ((uint16)b > 255U) 1472 | { 1473 | if (b < 0) 1474 | return 0; 1475 | else if (b > 255) 1476 | return 255; 1477 | } 1478 | 1479 | return (uint8)b; 1480 | } 1481 | /*----------------------------------------------------------------------------*/ 1482 | // 103/256 1483 | //R = Y + 1.402 (Cr-128) 1484 | 1485 | // 88/256, 183/256 1486 | //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128) 1487 | 1488 | // 198/256 1489 | //B = Y + 1.772 (Cb-128) 1490 | /*----------------------------------------------------------------------------*/ 1491 | // Cb upsample and accumulate, 4x4 to 8x8 1492 | static void upsampleCb(uint8 srcOfs, uint8 dstOfs) 1493 | { 1494 | // Cb - affects G and B 1495 | uint8 x, y; 1496 | int16* pSrc = gCoeffBuf + srcOfs; 1497 | uint8* pDstG = gMCUBufG + dstOfs; 1498 | uint8* pDstB = gMCUBufB + dstOfs; 1499 | for (y = 0; y < 4; y++) 1500 | { 1501 | for (x = 0; x < 4; x++) 1502 | { 1503 | uint8 cb = (uint8)*pSrc++; 1504 | int16 cbG, cbB; 1505 | 1506 | cbG = ((cb * 88U) >> 8U) - 44U; 1507 | pDstG[0] = subAndClamp(pDstG[0], cbG); 1508 | pDstG[1] = subAndClamp(pDstG[1], cbG); 1509 | pDstG[8] = subAndClamp(pDstG[8], cbG); 1510 | pDstG[9] = subAndClamp(pDstG[9], cbG); 1511 | 1512 | cbB = (cb + ((cb * 198U) >> 8U)) - 227U; 1513 | pDstB[0] = addAndClamp(pDstB[0], cbB); 1514 | pDstB[1] = addAndClamp(pDstB[1], cbB); 1515 | pDstB[8] = addAndClamp(pDstB[8], cbB); 1516 | pDstB[9] = addAndClamp(pDstB[9], cbB); 1517 | 1518 | pDstG += 2; 1519 | pDstB += 2; 1520 | } 1521 | 1522 | pSrc = pSrc - 4 + 8; 1523 | pDstG = pDstG - 8 + 16; 1524 | pDstB = pDstB - 8 + 16; 1525 | } 1526 | } 1527 | /*----------------------------------------------------------------------------*/ 1528 | // Cb upsample and accumulate, 4x8 to 8x8 1529 | static void upsampleCbH(uint8 srcOfs, uint8 dstOfs) 1530 | { 1531 | // Cb - affects G and B 1532 | uint8 x, y; 1533 | int16* pSrc = gCoeffBuf + srcOfs; 1534 | uint8* pDstG = gMCUBufG + dstOfs; 1535 | uint8* pDstB = gMCUBufB + dstOfs; 1536 | for (y = 0; y < 8; y++) 1537 | { 1538 | for (x = 0; x < 4; x++) 1539 | { 1540 | uint8 cb = (uint8)*pSrc++; 1541 | int16 cbG, cbB; 1542 | 1543 | cbG = ((cb * 88U) >> 8U) - 44U; 1544 | pDstG[0] = subAndClamp(pDstG[0], cbG); 1545 | pDstG[1] = subAndClamp(pDstG[1], cbG); 1546 | 1547 | cbB = (cb + ((cb * 198U) >> 8U)) - 227U; 1548 | pDstB[0] = addAndClamp(pDstB[0], cbB); 1549 | pDstB[1] = addAndClamp(pDstB[1], cbB); 1550 | 1551 | pDstG += 2; 1552 | pDstB += 2; 1553 | } 1554 | 1555 | pSrc = pSrc - 4 + 8; 1556 | } 1557 | } 1558 | /*----------------------------------------------------------------------------*/ 1559 | // Cb upsample and accumulate, 8x4 to 8x8 1560 | static void upsampleCbV(uint8 srcOfs, uint8 dstOfs) 1561 | { 1562 | // Cb - affects G and B 1563 | uint8 x, y; 1564 | int16* pSrc = gCoeffBuf + srcOfs; 1565 | uint8* pDstG = gMCUBufG + dstOfs; 1566 | uint8* pDstB = gMCUBufB + dstOfs; 1567 | for (y = 0; y < 4; y++) 1568 | { 1569 | for (x = 0; x < 8; x++) 1570 | { 1571 | uint8 cb = (uint8)*pSrc++; 1572 | int16 cbG, cbB; 1573 | 1574 | cbG = ((cb * 88U) >> 8U) - 44U; 1575 | pDstG[0] = subAndClamp(pDstG[0], cbG); 1576 | pDstG[8] = subAndClamp(pDstG[8], cbG); 1577 | 1578 | cbB = (cb + ((cb * 198U) >> 8U)) - 227U; 1579 | pDstB[0] = addAndClamp(pDstB[0], cbB); 1580 | pDstB[8] = addAndClamp(pDstB[8], cbB); 1581 | 1582 | ++pDstG; 1583 | ++pDstB; 1584 | } 1585 | 1586 | pDstG = pDstG - 8 + 16; 1587 | pDstB = pDstB - 8 + 16; 1588 | } 1589 | } 1590 | /*----------------------------------------------------------------------------*/ 1591 | // 103/256 1592 | //R = Y + 1.402 (Cr-128) 1593 | 1594 | // 88/256, 183/256 1595 | //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128) 1596 | 1597 | // 198/256 1598 | //B = Y + 1.772 (Cb-128) 1599 | /*----------------------------------------------------------------------------*/ 1600 | // Cr upsample and accumulate, 4x4 to 8x8 1601 | static void upsampleCr(uint8 srcOfs, uint8 dstOfs) 1602 | { 1603 | // Cr - affects R and G 1604 | uint8 x, y; 1605 | int16* pSrc = gCoeffBuf + srcOfs; 1606 | uint8* pDstR = gMCUBufR + dstOfs; 1607 | uint8* pDstG = gMCUBufG + dstOfs; 1608 | for (y = 0; y < 4; y++) 1609 | { 1610 | for (x = 0; x < 4; x++) 1611 | { 1612 | uint8 cr = (uint8)*pSrc++; 1613 | int16 crR, crG; 1614 | 1615 | crR = (cr + ((cr * 103U) >> 8U)) - 179; 1616 | pDstR[0] = addAndClamp(pDstR[0], crR); 1617 | pDstR[1] = addAndClamp(pDstR[1], crR); 1618 | pDstR[8] = addAndClamp(pDstR[8], crR); 1619 | pDstR[9] = addAndClamp(pDstR[9], crR); 1620 | 1621 | crG = ((cr * 183U) >> 8U) - 91; 1622 | pDstG[0] = subAndClamp(pDstG[0], crG); 1623 | pDstG[1] = subAndClamp(pDstG[1], crG); 1624 | pDstG[8] = subAndClamp(pDstG[8], crG); 1625 | pDstG[9] = subAndClamp(pDstG[9], crG); 1626 | 1627 | pDstR += 2; 1628 | pDstG += 2; 1629 | } 1630 | 1631 | pSrc = pSrc - 4 + 8; 1632 | pDstR = pDstR - 8 + 16; 1633 | pDstG = pDstG - 8 + 16; 1634 | } 1635 | } 1636 | /*----------------------------------------------------------------------------*/ 1637 | // Cr upsample and accumulate, 4x8 to 8x8 1638 | static void upsampleCrH(uint8 srcOfs, uint8 dstOfs) 1639 | { 1640 | // Cr - affects R and G 1641 | uint8 x, y; 1642 | int16* pSrc = gCoeffBuf + srcOfs; 1643 | uint8* pDstR = gMCUBufR + dstOfs; 1644 | uint8* pDstG = gMCUBufG + dstOfs; 1645 | for (y = 0; y < 8; y++) 1646 | { 1647 | for (x = 0; x < 4; x++) 1648 | { 1649 | uint8 cr = (uint8)*pSrc++; 1650 | int16 crR, crG; 1651 | 1652 | crR = (cr + ((cr * 103U) >> 8U)) - 179; 1653 | pDstR[0] = addAndClamp(pDstR[0], crR); 1654 | pDstR[1] = addAndClamp(pDstR[1], crR); 1655 | 1656 | crG = ((cr * 183U) >> 8U) - 91; 1657 | pDstG[0] = subAndClamp(pDstG[0], crG); 1658 | pDstG[1] = subAndClamp(pDstG[1], crG); 1659 | 1660 | pDstR += 2; 1661 | pDstG += 2; 1662 | } 1663 | 1664 | pSrc = pSrc - 4 + 8; 1665 | } 1666 | } 1667 | /*----------------------------------------------------------------------------*/ 1668 | // Cr upsample and accumulate, 8x4 to 8x8 1669 | static void upsampleCrV(uint8 srcOfs, uint8 dstOfs) 1670 | { 1671 | // Cr - affects R and G 1672 | uint8 x, y; 1673 | int16* pSrc = gCoeffBuf + srcOfs; 1674 | uint8* pDstR = gMCUBufR + dstOfs; 1675 | uint8* pDstG = gMCUBufG + dstOfs; 1676 | for (y = 0; y < 4; y++) 1677 | { 1678 | for (x = 0; x < 8; x++) 1679 | { 1680 | uint8 cr = (uint8)*pSrc++; 1681 | int16 crR, crG; 1682 | 1683 | crR = (cr + ((cr * 103U) >> 8U)) - 179; 1684 | pDstR[0] = addAndClamp(pDstR[0], crR); 1685 | pDstR[8] = addAndClamp(pDstR[8], crR); 1686 | 1687 | crG = ((cr * 183U) >> 8U) - 91; 1688 | pDstG[0] = subAndClamp(pDstG[0], crG); 1689 | pDstG[8] = subAndClamp(pDstG[8], crG); 1690 | 1691 | ++pDstR; 1692 | ++pDstG; 1693 | } 1694 | 1695 | pDstR = pDstR - 8 + 16; 1696 | pDstG = pDstG - 8 + 16; 1697 | } 1698 | } 1699 | /*----------------------------------------------------------------------------*/ 1700 | // Convert Y to RGB 1701 | static void copyY(uint8 dstOfs) 1702 | { 1703 | uint8 i; 1704 | uint8* pRDst = gMCUBufR + dstOfs; 1705 | uint8* pGDst = gMCUBufG + dstOfs; 1706 | uint8* pBDst = gMCUBufB + dstOfs; 1707 | int16* pSrc = gCoeffBuf; 1708 | 1709 | for (i = 64; i > 0; i--) 1710 | { 1711 | uint8 c = (uint8)*pSrc++; 1712 | 1713 | *pRDst++ = c; 1714 | *pGDst++ = c; 1715 | *pBDst++ = c; 1716 | } 1717 | } 1718 | /*----------------------------------------------------------------------------*/ 1719 | // Cb convert to RGB and accumulate 1720 | static void convertCb(uint8 dstOfs) 1721 | { 1722 | uint8 i; 1723 | uint8* pDstG = gMCUBufG + dstOfs; 1724 | uint8* pDstB = gMCUBufB + dstOfs; 1725 | int16* pSrc = gCoeffBuf; 1726 | 1727 | for (i = 64; i > 0; i--) 1728 | { 1729 | uint8 cb = (uint8)*pSrc++; 1730 | int16 cbG, cbB; 1731 | 1732 | cbG = ((cb * 88U) >> 8U) - 44U; 1733 | *pDstG++ = subAndClamp(pDstG[0], cbG); 1734 | 1735 | cbB = (cb + ((cb * 198U) >> 8U)) - 227U; 1736 | *pDstB++ = addAndClamp(pDstB[0], cbB); 1737 | } 1738 | } 1739 | /*----------------------------------------------------------------------------*/ 1740 | // Cr convert to RGB and accumulate 1741 | static void convertCr(uint8 dstOfs) 1742 | { 1743 | uint8 i; 1744 | uint8* pDstR = gMCUBufR + dstOfs; 1745 | uint8* pDstG = gMCUBufG + dstOfs; 1746 | int16* pSrc = gCoeffBuf; 1747 | 1748 | for (i = 64; i > 0; i--) 1749 | { 1750 | uint8 cr = (uint8)*pSrc++; 1751 | int16 crR, crG; 1752 | 1753 | crR = (cr + ((cr * 103U) >> 8U)) - 179; 1754 | *pDstR++ = addAndClamp(pDstR[0], crR); 1755 | 1756 | crG = ((cr * 183U) >> 8U) - 91; 1757 | *pDstG++ = subAndClamp(pDstG[0], crG); 1758 | } 1759 | } 1760 | /*----------------------------------------------------------------------------*/ 1761 | static void transformBlock(uint8 mcuBlock) 1762 | { 1763 | idctRows(); 1764 | idctCols(); 1765 | 1766 | switch (gScanType) 1767 | { 1768 | case PJPG_GRAYSCALE: 1769 | { 1770 | // MCU size: 1, 1 block per MCU 1771 | copyY(0); 1772 | break; 1773 | } 1774 | case PJPG_YH1V1: 1775 | { 1776 | // MCU size: 8x8, 3 blocks per MCU 1777 | switch (mcuBlock) 1778 | { 1779 | case 0: 1780 | { 1781 | copyY(0); 1782 | break; 1783 | } 1784 | case 1: 1785 | { 1786 | convertCb(0); 1787 | break; 1788 | } 1789 | case 2: 1790 | { 1791 | convertCr(0); 1792 | break; 1793 | } 1794 | } 1795 | 1796 | break; 1797 | } 1798 | case PJPG_YH1V2: 1799 | { 1800 | // MCU size: 8x16, 4 blocks per MCU 1801 | switch (mcuBlock) 1802 | { 1803 | case 0: 1804 | { 1805 | copyY(0); 1806 | break; 1807 | } 1808 | case 1: 1809 | { 1810 | copyY(128); 1811 | break; 1812 | } 1813 | case 2: 1814 | { 1815 | upsampleCbV(0, 0); 1816 | upsampleCbV(4*8, 128); 1817 | break; 1818 | } 1819 | case 3: 1820 | { 1821 | upsampleCrV(0, 0); 1822 | upsampleCrV(4*8, 128); 1823 | break; 1824 | } 1825 | } 1826 | 1827 | break; 1828 | } 1829 | case PJPG_YH2V1: 1830 | { 1831 | // MCU size: 16x8, 4 blocks per MCU 1832 | switch (mcuBlock) 1833 | { 1834 | case 0: 1835 | { 1836 | copyY(0); 1837 | break; 1838 | } 1839 | case 1: 1840 | { 1841 | copyY(64); 1842 | break; 1843 | } 1844 | case 2: 1845 | { 1846 | upsampleCbH(0, 0); 1847 | upsampleCbH(4, 64); 1848 | break; 1849 | } 1850 | case 3: 1851 | { 1852 | upsampleCrH(0, 0); 1853 | upsampleCrH(4, 64); 1854 | break; 1855 | } 1856 | } 1857 | 1858 | break; 1859 | } 1860 | case PJPG_YH2V2: 1861 | { 1862 | // MCU size: 16x16, 6 blocks per MCU 1863 | switch (mcuBlock) 1864 | { 1865 | case 0: 1866 | { 1867 | copyY(0); 1868 | break; 1869 | } 1870 | case 1: 1871 | { 1872 | copyY(64); 1873 | break; 1874 | } 1875 | case 2: 1876 | { 1877 | copyY(128); 1878 | break; 1879 | } 1880 | case 3: 1881 | { 1882 | copyY(192); 1883 | break; 1884 | } 1885 | case 4: 1886 | { 1887 | upsampleCb(0, 0); 1888 | upsampleCb(4, 64); 1889 | upsampleCb(4*8, 128); 1890 | upsampleCb(4+4*8, 192); 1891 | break; 1892 | } 1893 | case 5: 1894 | { 1895 | upsampleCr(0, 0); 1896 | upsampleCr(4, 64); 1897 | upsampleCr(4*8, 128); 1898 | upsampleCr(4+4*8, 192); 1899 | break; 1900 | } 1901 | } 1902 | 1903 | break; 1904 | } 1905 | } 1906 | } 1907 | //------------------------------------------------------------------------------ 1908 | static void transformBlockReduce(uint8 mcuBlock) 1909 | { 1910 | uint8 c = clamp(PJPG_DESCALE(gCoeffBuf[0]) + 128); 1911 | int16 cbG, cbB, crR, crG; 1912 | 1913 | switch (gScanType) 1914 | { 1915 | case PJPG_GRAYSCALE: 1916 | { 1917 | // MCU size: 1, 1 block per MCU 1918 | gMCUBufR[0] = c; 1919 | break; 1920 | } 1921 | case PJPG_YH1V1: 1922 | { 1923 | // MCU size: 8x8, 3 blocks per MCU 1924 | switch (mcuBlock) 1925 | { 1926 | case 0: 1927 | { 1928 | gMCUBufR[0] = c; 1929 | gMCUBufG[0] = c; 1930 | gMCUBufB[0] = c; 1931 | break; 1932 | } 1933 | case 1: 1934 | { 1935 | cbG = ((c * 88U) >> 8U) - 44U; 1936 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], cbG); 1937 | 1938 | cbB = (c + ((c * 198U) >> 8U)) - 227U; 1939 | gMCUBufB[0] = addAndClamp(gMCUBufB[0], cbB); 1940 | break; 1941 | } 1942 | case 2: 1943 | { 1944 | crR = (c + ((c * 103U) >> 8U)) - 179; 1945 | gMCUBufR[0] = addAndClamp(gMCUBufR[0], crR); 1946 | 1947 | crG = ((c * 183U) >> 8U) - 91; 1948 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], crG); 1949 | break; 1950 | } 1951 | } 1952 | 1953 | break; 1954 | } 1955 | case PJPG_YH1V2: 1956 | { 1957 | // MCU size: 8x16, 4 blocks per MCU 1958 | switch (mcuBlock) 1959 | { 1960 | case 0: 1961 | { 1962 | gMCUBufR[0] = c; 1963 | gMCUBufG[0] = c; 1964 | gMCUBufB[0] = c; 1965 | break; 1966 | } 1967 | case 1: 1968 | { 1969 | gMCUBufR[128] = c; 1970 | gMCUBufG[128] = c; 1971 | gMCUBufB[128] = c; 1972 | break; 1973 | } 1974 | case 2: 1975 | { 1976 | cbG = ((c * 88U) >> 8U) - 44U; 1977 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], cbG); 1978 | gMCUBufG[128] = subAndClamp(gMCUBufG[128], cbG); 1979 | 1980 | cbB = (c + ((c * 198U) >> 8U)) - 227U; 1981 | gMCUBufB[0] = addAndClamp(gMCUBufB[0], cbB); 1982 | gMCUBufB[128] = addAndClamp(gMCUBufB[128], cbB); 1983 | 1984 | break; 1985 | } 1986 | case 3: 1987 | { 1988 | crR = (c + ((c * 103U) >> 8U)) - 179; 1989 | gMCUBufR[0] = addAndClamp(gMCUBufR[0], crR); 1990 | gMCUBufR[128] = addAndClamp(gMCUBufR[128], crR); 1991 | 1992 | crG = ((c * 183U) >> 8U) - 91; 1993 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], crG); 1994 | gMCUBufG[128] = subAndClamp(gMCUBufG[128], crG); 1995 | 1996 | break; 1997 | } 1998 | } 1999 | break; 2000 | } 2001 | case PJPG_YH2V1: 2002 | { 2003 | // MCU size: 16x8, 4 blocks per MCU 2004 | switch (mcuBlock) 2005 | { 2006 | case 0: 2007 | { 2008 | gMCUBufR[0] = c; 2009 | gMCUBufG[0] = c; 2010 | gMCUBufB[0] = c; 2011 | break; 2012 | } 2013 | case 1: 2014 | { 2015 | gMCUBufR[64] = c; 2016 | gMCUBufG[64] = c; 2017 | gMCUBufB[64] = c; 2018 | break; 2019 | } 2020 | case 2: 2021 | { 2022 | cbG = ((c * 88U) >> 8U) - 44U; 2023 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], cbG); 2024 | gMCUBufG[64] = subAndClamp(gMCUBufG[64], cbG); 2025 | 2026 | cbB = (c + ((c * 198U) >> 8U)) - 227U; 2027 | gMCUBufB[0] = addAndClamp(gMCUBufB[0], cbB); 2028 | gMCUBufB[64] = addAndClamp(gMCUBufB[64], cbB); 2029 | 2030 | break; 2031 | } 2032 | case 3: 2033 | { 2034 | crR = (c + ((c * 103U) >> 8U)) - 179; 2035 | gMCUBufR[0] = addAndClamp(gMCUBufR[0], crR); 2036 | gMCUBufR[64] = addAndClamp(gMCUBufR[64], crR); 2037 | 2038 | crG = ((c * 183U) >> 8U) - 91; 2039 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], crG); 2040 | gMCUBufG[64] = subAndClamp(gMCUBufG[64], crG); 2041 | 2042 | break; 2043 | } 2044 | } 2045 | break; 2046 | } 2047 | case PJPG_YH2V2: 2048 | { 2049 | // MCU size: 16x16, 6 blocks per MCU 2050 | switch (mcuBlock) 2051 | { 2052 | case 0: 2053 | { 2054 | gMCUBufR[0] = c; 2055 | gMCUBufG[0] = c; 2056 | gMCUBufB[0] = c; 2057 | break; 2058 | } 2059 | case 1: 2060 | { 2061 | gMCUBufR[64] = c; 2062 | gMCUBufG[64] = c; 2063 | gMCUBufB[64] = c; 2064 | break; 2065 | } 2066 | case 2: 2067 | { 2068 | gMCUBufR[128] = c; 2069 | gMCUBufG[128] = c; 2070 | gMCUBufB[128] = c; 2071 | break; 2072 | } 2073 | case 3: 2074 | { 2075 | gMCUBufR[192] = c; 2076 | gMCUBufG[192] = c; 2077 | gMCUBufB[192] = c; 2078 | break; 2079 | } 2080 | case 4: 2081 | { 2082 | cbG = ((c * 88U) >> 8U) - 44U; 2083 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], cbG); 2084 | gMCUBufG[64] = subAndClamp(gMCUBufG[64], cbG); 2085 | gMCUBufG[128] = subAndClamp(gMCUBufG[128], cbG); 2086 | gMCUBufG[192] = subAndClamp(gMCUBufG[192], cbG); 2087 | 2088 | cbB = (c + ((c * 198U) >> 8U)) - 227U; 2089 | gMCUBufB[0] = addAndClamp(gMCUBufB[0], cbB); 2090 | gMCUBufB[64] = addAndClamp(gMCUBufB[64], cbB); 2091 | gMCUBufB[128] = addAndClamp(gMCUBufB[128], cbB); 2092 | gMCUBufB[192] = addAndClamp(gMCUBufB[192], cbB); 2093 | 2094 | break; 2095 | } 2096 | case 5: 2097 | { 2098 | crR = (c + ((c * 103U) >> 8U)) - 179; 2099 | gMCUBufR[0] = addAndClamp(gMCUBufR[0], crR); 2100 | gMCUBufR[64] = addAndClamp(gMCUBufR[64], crR); 2101 | gMCUBufR[128] = addAndClamp(gMCUBufR[128], crR); 2102 | gMCUBufR[192] = addAndClamp(gMCUBufR[192], crR); 2103 | 2104 | crG = ((c * 183U) >> 8U) - 91; 2105 | gMCUBufG[0] = subAndClamp(gMCUBufG[0], crG); 2106 | gMCUBufG[64] = subAndClamp(gMCUBufG[64], crG); 2107 | gMCUBufG[128] = subAndClamp(gMCUBufG[128], crG); 2108 | gMCUBufG[192] = subAndClamp(gMCUBufG[192], crG); 2109 | 2110 | break; 2111 | } 2112 | } 2113 | break; 2114 | } 2115 | } 2116 | } 2117 | //------------------------------------------------------------------------------ 2118 | static uint8 decodeNextMCU(void) 2119 | { 2120 | uint8 status; 2121 | uint8 mcuBlock; 2122 | 2123 | if (gRestartInterval) 2124 | { 2125 | if (gRestartsLeft == 0) 2126 | { 2127 | status = processRestart(); 2128 | if (status) 2129 | return status; 2130 | } 2131 | gRestartsLeft--; 2132 | } 2133 | 2134 | for (mcuBlock = 0; mcuBlock < gMaxBlocksPerMCU; mcuBlock++) 2135 | { 2136 | uint8 componentID = gMCUOrg[mcuBlock]; 2137 | uint8 compQuant = gCompQuant[componentID]; 2138 | uint8 compDCTab = gCompDCTab[componentID]; 2139 | uint8 numExtraBits, compACTab, k; 2140 | const int16* pQ = compQuant ? gQuant1 : gQuant0; 2141 | uint16 r, dc; 2142 | 2143 | uint8 s = huffDecode(compDCTab ? &gHuffTab1 : &gHuffTab0, compDCTab ? gHuffVal1 : gHuffVal0); 2144 | 2145 | r = 0; 2146 | numExtraBits = s & 0xF; 2147 | if (numExtraBits) 2148 | r = getBits2(numExtraBits); 2149 | dc = huffExtend(r, s); 2150 | 2151 | dc = dc + gLastDC[componentID]; 2152 | gLastDC[componentID] = dc; 2153 | 2154 | gCoeffBuf[0] = dc * pQ[0]; 2155 | 2156 | compACTab = gCompACTab[componentID]; 2157 | 2158 | if (gReduce) 2159 | { 2160 | // Decode, but throw out the AC coefficients in reduce mode. 2161 | for (k = 1; k < 64; k++) 2162 | { 2163 | s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2); 2164 | 2165 | numExtraBits = s & 0xF; 2166 | if (numExtraBits) 2167 | getBits2(numExtraBits); 2168 | 2169 | r = s >> 4; 2170 | s &= 15; 2171 | 2172 | if (s) 2173 | { 2174 | if (r) 2175 | { 2176 | if ((k + r) > 63) 2177 | return PJPG_DECODE_ERROR; 2178 | 2179 | k = (uint8)(k + r); 2180 | } 2181 | } 2182 | else 2183 | { 2184 | if (r == 15) 2185 | { 2186 | if ((k + 16) > 64) 2187 | return PJPG_DECODE_ERROR; 2188 | 2189 | k += (16 - 1); // - 1 because the loop counter is k 2190 | } 2191 | else 2192 | break; 2193 | } 2194 | } 2195 | 2196 | transformBlockReduce(mcuBlock); 2197 | } 2198 | else 2199 | { 2200 | // Decode and dequantize AC coefficients 2201 | for (k = 1; k < 64; k++) 2202 | { 2203 | uint16 extraBits; 2204 | 2205 | s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2); 2206 | 2207 | extraBits = 0; 2208 | numExtraBits = s & 0xF; 2209 | if (numExtraBits) 2210 | extraBits = getBits2(numExtraBits); 2211 | 2212 | r = s >> 4; 2213 | s &= 15; 2214 | 2215 | if (s) 2216 | { 2217 | int16 ac; 2218 | 2219 | if (r) 2220 | { 2221 | if ((k + r) > 63) 2222 | return PJPG_DECODE_ERROR; 2223 | 2224 | while (r) 2225 | { 2226 | gCoeffBuf[ZAG[k++]] = 0; 2227 | r--; 2228 | } 2229 | } 2230 | 2231 | ac = huffExtend(extraBits, s); 2232 | 2233 | gCoeffBuf[ZAG[k]] = ac * pQ[k]; 2234 | } 2235 | else 2236 | { 2237 | if (r == 15) 2238 | { 2239 | if ((k + 16) > 64) 2240 | return PJPG_DECODE_ERROR; 2241 | 2242 | for (r = 16; r > 0; r--) 2243 | gCoeffBuf[ZAG[k++]] = 0; 2244 | 2245 | k--; // - 1 because the loop counter is k 2246 | } 2247 | else 2248 | break; 2249 | } 2250 | } 2251 | 2252 | while (k < 64) 2253 | gCoeffBuf[ZAG[k++]] = 0; 2254 | 2255 | transformBlock(mcuBlock); 2256 | } 2257 | } 2258 | 2259 | return 0; 2260 | } 2261 | //------------------------------------------------------------------------------ 2262 | unsigned char pjpeg_decode_mcu(void) 2263 | { 2264 | uint8 status; 2265 | 2266 | if (gCallbackStatus) 2267 | return gCallbackStatus; 2268 | 2269 | if ((!gNumMCUSRemainingX) && (!gNumMCUSRemainingY)) 2270 | return PJPG_NO_MORE_BLOCKS; 2271 | 2272 | status = decodeNextMCU(); 2273 | if ((status) || (gCallbackStatus)) 2274 | return gCallbackStatus ? gCallbackStatus : status; 2275 | 2276 | gNumMCUSRemainingX--; 2277 | if (!gNumMCUSRemainingX) 2278 | { 2279 | gNumMCUSRemainingY--; 2280 | if (gNumMCUSRemainingY > 0) 2281 | gNumMCUSRemainingX = gMaxMCUSPerRow; 2282 | } 2283 | 2284 | return 0; 2285 | } 2286 | //------------------------------------------------------------------------------ 2287 | unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data, unsigned char reduce) 2288 | { 2289 | uint8 status; 2290 | 2291 | pInfo->m_width = 0; pInfo->m_height = 0; pInfo->m_comps = 0; 2292 | pInfo->m_MCUSPerRow = 0; pInfo->m_MCUSPerCol = 0; 2293 | pInfo->m_scanType = PJPG_GRAYSCALE; 2294 | pInfo->m_MCUWidth = 0; pInfo->m_MCUHeight = 0; 2295 | pInfo->m_pMCUBufR = (unsigned char*)0; pInfo->m_pMCUBufG = (unsigned char*)0; pInfo->m_pMCUBufB = (unsigned char*)0; 2296 | 2297 | g_pNeedBytesCallback = pNeed_bytes_callback; 2298 | g_pCallback_data = pCallback_data; 2299 | gCallbackStatus = 0; 2300 | gReduce = reduce; 2301 | 2302 | status = init(); 2303 | if ((status) || (gCallbackStatus)) 2304 | return gCallbackStatus ? gCallbackStatus : status; 2305 | 2306 | status = locateSOFMarker(); 2307 | if ((status) || (gCallbackStatus)) 2308 | return gCallbackStatus ? gCallbackStatus : status; 2309 | 2310 | status = initFrame(); 2311 | if ((status) || (gCallbackStatus)) 2312 | return gCallbackStatus ? gCallbackStatus : status; 2313 | 2314 | status = initScan(); 2315 | if ((status) || (gCallbackStatus)) 2316 | return gCallbackStatus ? gCallbackStatus : status; 2317 | 2318 | pInfo->m_width = gImageXSize; pInfo->m_height = gImageYSize; pInfo->m_comps = gCompsInFrame; 2319 | pInfo->m_scanType = gScanType; 2320 | pInfo->m_MCUSPerRow = gMaxMCUSPerRow; pInfo->m_MCUSPerCol = gMaxMCUSPerCol; 2321 | pInfo->m_MCUWidth = gMaxMCUXSize; pInfo->m_MCUHeight = gMaxMCUYSize; 2322 | pInfo->m_pMCUBufR = gMCUBufR; pInfo->m_pMCUBufG = gMCUBufG; pInfo->m_pMCUBufB = gMCUBufB; 2323 | 2324 | return 0; 2325 | } 2326 | --------------------------------------------------------------------------------