| /** | |
| ****************************************************************************** | |
| * @file jpeg_utils.c | |
| * @author MCD Application Team | |
| * @version V2.0.0 | |
| * @date 3-June-2016 | |
| * @brief This driver provides JPEG MCU (Minimum Coded Unit) blocks to RGB and RGB to JPEG MCU conversion functions. | |
| * | |
| * The STM32 HW JPEG decoder/encoder peripheral allows to decode/encode jpeg images. | |
| * In decoding, the STM32 HW JPEG data output are organized in blocks called MCU (Minimum Coded Unit) | |
| * as specified in the jpeg standard. | |
| * In encoding, the STM32 HW JPEG data input must be organized in MCU blocks. | |
| * Depending of the image color space and chrominance sampling, an MCU is generally organized in : | |
| * N luminance (Y) blocks + a Blue chrominance (Cb) block + a Red chrominance (Cr) block. | |
| * Each block size is 8x8 samples. | |
| * | |
| * The STM32 HW JPEG supports 3 possible color space : | |
| * - YCbCr : an MCU is composed of 3 color components : Y , Cb and Cr | |
| * - GrayScale : an MCU is composed of 1 single color component : Y | |
| * - CMYK : an MCU is composed of 4 color components : Cyan, Magenta, Yellow, and Key (blacK) | |
| * | |
| * This utility file should be used on top of the STM32 HAL JPEG driver. | |
| * In decoding, it allows to convert MCU blocks to RGB888 or ARGB8888 pixels stored to a destination | |
| * frame buffer that can be displayed. | |
| * In encoding, it allows to convert RGB888 or ARGB8888 pixels to MCU blocks. | |
| * | |
| * This utility supports following MCU Chroma sampling format and color space : | |
| * - YCbCr 4:2:0 : Each MCU is composed of 4 Y 8x8 blocks + 1 Cb 8x8 block + Cr 8x8 block | |
| * - YCbCr 4:2:2 : Each MCU is composed of 2 Y 8x8 blocks + 1 Cb 8x8 block + Cr 8x8 block | |
| * - YCbCr 4:4:4 : Each MCU is composed of 1 Y 8x8 block + 1 Cb 8x8 block + Cr 8x8 block | |
| * - GrayScale : Each MCU is composed of 1 Y 8x8 block | |
| * - CMYK : Each MCU is composed of 1 Cyan 8x8 block + 1 Magenta 8x8 block + 1 Yellow 8x8 block + 1 Key 8x8 block. | |
| * | |
| * | |
| * @How to use this driver | |
| * | |
| * - The configuration file "jpeg_utils_conf_template.h" is used to configure this utility | |
| * providing some useful flexibilities. | |
| * This file should be copied to the application folder and modified as follows: | |
| * - Rename it to "jpeg_utils_conf.h". | |
| * - Update the name of the JPEG driver's header file, depending on the EVAL board you are using. | |
| * | |
| * Example if using the STM32F769I-EVAL board : | |
| * - Copy the file "jpeg_utils_conf_template.h" to the application folder and rename it to "jpeg_utils_conf.h" | |
| * - Edit the "jpeg_utils_conf.h" and change lines 51 and 52 as follow : | |
| * #include "stm32f7xx_hal.h" | |
| * #include "stm32f7xx_hal_jpeg.h" | |
| * | |
| * Using this configuration file, user can change the following settings: | |
| * - Use RGB888 or ARGB8888 or RGB565 by setting the constant JPEG_RGB_FORMAT respectively to JPEG_RGB888, JPEG_ARGB8888 JPEG_RGB565. | |
| * - Swap RED, and Blue offsets if user needs to change the color order to BGR (instead of RGB) by setting: | |
| * #define JPEG_SWAP_RB 1 | |
| * - Enable or disable the decoding post-processing functions (YCbCr to RGB conversion functions) by setting the define USE_JPEG_DECODER | |
| * respectively to 0 or 1. | |
| * - Enable or disable the encoding pre-processing functions (RGB to YCbCr conversion functions) by setting the define USE_JPEG_ENCODER | |
| * respectively to 0 or 1. | |
| * | |
| * * For Decoding: | |
| * - First, function "JPEG_InitColorTables" should be called to initialize the YCbCr to RGB color | |
| * conversion tables. This function needs to be called only one time at the beginning of the | |
| * program whatever the number of jpeg files to be decoded. | |
| * | |
| * - As soon as the JPEG HW peripheral finished parsing the header of the JPEG input file, | |
| * the HAL JPEG callback "HAL_JPEG_InfoReadyCallback" is launched providing the jpeg file | |
| * characteristics found in its header. | |
| * User can then call the utility function "JPEG_GetDecodeColorConvertFunc" with these | |
| * information and retrieve the corresponding color conversion function and number of MCUs. | |
| * | |
| * Then each time an integer number of MCUs are available (from the HW JPEG output), user | |
| * can call the retrieved function to convert these HW JPEG output data to RGB888 or | |
| * ARGB8888 pixel stored to the specified destination buffer. | |
| * | |
| * * For Encoding: | |
| * - First, function "JPEG_InitColorTables" should be called to initialize the YCbCr/RGB color | |
| * conversion tables. This function needs to be called only one time at the beginning of the | |
| * program whatever the number of jpeg files to be encoded or decoded. | |
| * | |
| * - First Use the utility function "JPEG_GetEncodeColorConvertFunc" with the input image informations | |
| * to retrieve the corresponding color conversion function and number of MCUs. | |
| * | |
| * Then each time an RGB input buffer is available, user can call the retrieved function to convert | |
| * RGB data to MCU blocks stored to the specified destination buffer. | |
| * | |
| * | |
| ****************************************************************************** | |
| * @attention | |
| * | |
| * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2> | |
| * | |
| * Redistribution and use in source and binary forms, with or without modification, | |
| * are permitted provided that the following conditions are met: | |
| * 1. Redistributions of source code must retain the above copyright notice, | |
| * this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| * this list of conditions and the following disclaimer in the documentation | |
| * and/or other materials provided with the distribution. | |
| * 3. Neither the name of STMicroelectronics nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| ****************************************************************************** | |
| */ | |
| /* Includes ------------------------------------------------------------------*/ | |
| #include "jpeg_utils.h" | |
| /** @addtogroup Utilities | |
| * @{ | |
| */ | |
| /** @defgroup JPEG JPEG | |
| * @brief JPEG YCbCr blocks <-> RGB conversion utilties | |
| * @{ | |
| */ | |
| /** @defgroup JPEG_Private_Types JPEG Private Types | |
| * @{ | |
| */ | |
| /* Private typedef -----------------------------------------------------------*/ | |
| typedef struct __JPEG_MCU_RGB_ConvertorTypeDef | |
| { | |
| uint32_t ColorSpace; | |
| uint32_t ChromaSubsampling; | |
| uint32_t ImageWidth; | |
| uint32_t ImageHeight; | |
| uint32_t ImageSize_Bytes; | |
| uint32_t LineOffset; | |
| uint32_t BlockSize; | |
| uint32_t H_factor; | |
| uint32_t V_factor; | |
| uint32_t WidthExtend; | |
| uint32_t ScaledWidth; | |
| uint32_t MCU_Total_Nb; | |
| uint16_t *Y_MCU_LUT; | |
| uint16_t *Cb_MCU_LUT; | |
| uint16_t *Cr_MCU_LUT; | |
| uint16_t *K_MCU_LUT; | |
| }JPEG_MCU_RGB_ConvertorTypeDef; | |
| /** | |
| * @} | |
| */ | |
| /** @defgroup JPEG_Private_Defines JPEG Private Defines | |
| * @{ | |
| */ | |
| /* Private define ------------------------------------------------------------*/ | |
| #define YCBCR_420_BLOCK_SIZE 384 /* YCbCr 4:2:0 MCU : 4 8x8 blocks of Y + 1 8x8 block of Cb + 1 8x8 block of Cr */ | |
| #define YCBCR_422_BLOCK_SIZE 256 /* YCbCr 4:2:2 MCU : 2 8x8 blocks of Y + 1 8x8 block of Cb + 1 8x8 block of Cr */ | |
| #define YCBCR_444_BLOCK_SIZE 192 /* YCbCr 4:4:4 MCU : 1 8x8 block of Y + 1 8x8 block of Cb + 1 8x8 block of Cr */ | |
| #define GRAY_444_BLOCK_SIZE 64 /* GrayScale MCU : 1 8x8 block of Y */ | |
| #define CMYK_444_BLOCK_SIZE 256 /* CMYK MCU : 1 8x8 blocks of Cyan + 1 8x8 block Magenta + 1 8x8 block of Yellow and 1 8x8 block of BlacK */ | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| #define JPEG_GREEN_OFFSET 8 /* Offset of the GREEN color in a pixel */ | |
| #define JPEG_ALPHA_OFFSET 24 /* Offset of the Transparency Alpha in a pixel */ | |
| #define JPEG_BYTES_PER_PIXEL 4 /* Number of bytes in a pixel */ | |
| #if (JPEG_SWAP_RB == 0) | |
| #define JPEG_RED_OFFSET 16 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 0 /* Offset of the BLUE color in a pixel */ | |
| #else | |
| #define JPEG_RED_OFFSET 0 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 16 /* Offset of the BLUE color in a pixel */ | |
| #endif /* JPEG_SWAP_RB */ | |
| #elif(JPEG_RGB_FORMAT == JPEG_RGB888) | |
| #define JPEG_GREEN_OFFSET 8 /* Offset of the GREEN color in a pixel */ | |
| #define JPEG_BYTES_PER_PIXEL 3 /* Number of bytes in a pixel */ | |
| #if (JPEG_SWAP_RB == 0) | |
| #define JPEG_RED_OFFSET 16 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 0 /* Offset of the BLUE color in a pixel */ | |
| #else | |
| #define JPEG_RED_OFFSET 0 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 16 /* Offset of the BLUE color in a pixel */ | |
| #endif /* JPEG_SWAP_RB */ | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| #define JPEG_GREEN_OFFSET 5 /* Offset of the GREEN color in a pixel */ | |
| #define JPEG_BYTES_PER_PIXEL 2 /* Number of bytes in a pixel */ | |
| #define JPEG_RGB565_GREEN_MASK 0x07E0 /* Mask of Green component in RGB565 Format */ | |
| #if (JPEG_SWAP_RB == 0) | |
| #define JPEG_RED_OFFSET 11 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 0 /* Offset of the BLUE color in a pixel */ | |
| #define JPEG_RGB565_RED_MASK 0xF800 /* Mask of Red component in RGB565 Format */ | |
| #define JPEG_RGB565_BLUE_MASK 0x001F /* Mask of Blue component in RGB565 Format */ | |
| #else | |
| #define JPEG_RED_OFFSET 0 /* Offset of the RED color in a pixel */ | |
| #define JPEG_BLUE_OFFSET 11 /* Offset of the BLUE color in a pixel */ | |
| #define JPEG_RGB565_RED_MASK 0x001F /* Mask of Red component in RGB565 Format */ | |
| #define JPEG_RGB565_BLUE_MASK 0xF800 /* Mask of Blue component in RGB565 Format */ | |
| #endif /* JPEG_SWAP_RB */ | |
| #else | |
| #error "unknown JPEG_RGB_FORMAT " | |
| #endif /* JPEG_RGB_FORMAT */ | |
| /** | |
| * @} | |
| */ | |
| /** @defgroup JPEG_Private_Macros JPEG Private Macros | |
| * @{ | |
| */ | |
| /* Private macro -------------------------------------------------------------*/ | |
| #if (USE_JPEG_DECODER == 1) | |
| #define CLAMP(value) CLAMP_LUT[(value) + 0x100] /* Range limitting macro */ | |
| #endif | |
| #if (USE_JPEG_ENCODER == 1) | |
| #define MAX(val1,val2) ((val1 > val2) ? val1 : val2) | |
| #endif | |
| /** | |
| * @} | |
| */ | |
| /** @defgroup JPEG_Private_Variables JPEG Private Variables | |
| * @{ | |
| */ | |
| /* Private variables ---------------------------------------------------------*/ | |
| static JPEG_MCU_RGB_ConvertorTypeDef JPEG_ConvertorParams; | |
| #if (USE_JPEG_DECODER == 1) | |
| static int32_t CR_RED_LUT[256]; /* Cr to Red color conversion Look Up Table */ | |
| static int32_t CB_BLUE_LUT[256]; /* Cb to Blue color conversion Look Up Table */ | |
| static int32_t CR_GREEN_LUT[256]; /* Cr to Green color conversion Look Up Table*/ | |
| static int32_t CB_GREEN_LUT[256]; /* Cb to Green color conversion Look Up Table*/ | |
| #endif /* USE_JPEG_DECODER == 1 */ | |
| #if (USE_JPEG_ENCODER == 1) | |
| static int32_t RED_Y_LUT[256]; /* Red to Y color conversion Look Up Table */ | |
| static int32_t RED_CB_LUT[256]; /* Red to Cb color conversion Look Up Table */ | |
| static int32_t BLUE_CB_RED_CR_LUT[256]; /* Red to Cr and Blue to Cb color conversion Look Up Table */ | |
| static int32_t GREEN_Y_LUT[256]; /* Green to Y color conversion Look Up Table*/ | |
| static int32_t GREEN_CR_LUT[256]; /* Green to Cr color conversion Look Up Table*/ | |
| static int32_t GREEN_CB_LUT[256]; /* Green to Cb color conversion Look Up Table*/ | |
| static int32_t BLUE_Y_LUT[256]; /* Blue to Y color conversion Look Up Table */ | |
| static int32_t BLUE_CR_LUT[256]; /* Blue to Cr color conversion Look Up Table */ | |
| /* Different MCU Look Up Table */ | |
| static uint16_t JPEG_Y_MCU_LUT[256]; | |
| static uint16_t JPEG_Y_MCU_444_LUT[64]; | |
| static uint16_t JPEG_Cb_MCU_420_LUT[256]; | |
| static uint16_t JPEG_Cb_MCU_422_LUT[256]; | |
| static uint16_t JPEG_Cb_MCU_444_LUT[64]; | |
| static uint16_t JPEG_Cr_MCU_420_LUT[256]; | |
| static uint16_t JPEG_Cr_MCU_422_LUT[256]; | |
| static uint16_t JPEG_Cr_MCU_444_LUT[64]; | |
| static uint16_t JPEG_K_MCU_420_LUT[256]; | |
| static uint16_t JPEG_K_MCU_422_LUT[256]; | |
| static uint16_t JPEG_K_MCU_444_LUT[64]; | |
| /* YCCK format blocks */ | |
| uint8_t kBlocks[16][16]; | |
| #endif /* USE_JPEG_ENCODER == 1 */ | |
| #if (USE_JPEG_DECODER == 1) | |
| /* color clamp table : used for range limitting */ | |
| static const uint8_t CLAMP_LUT[] = { | |
| /* clamp range 0xffffffff to 0xffffff00 */ | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| /* clamp range 0x00 to 0xff */ | |
| 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
| 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, | |
| 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, | |
| 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | |
| 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, | |
| 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | |
| 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, | |
| 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, | |
| 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, | |
| 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, | |
| 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, | |
| 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, | |
| 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, | |
| 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, | |
| 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, | |
| /* clamp range 0x100 to 0x1ff */ | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| }; | |
| #endif /* USE_JPEG_DECODER == 1 */ | |
| /** | |
| * @} | |
| */ | |
| /** @defgroup JPEG_Private_FunctionPrototypes JPEG Private FunctionPrototypes | |
| * @{ | |
| */ | |
| /* Private function prototypes -----------------------------------------------*/ | |
| #if (USE_JPEG_ENCODER == 1) | |
| static uint32_t JPEG_ARGB_MCU_YCbCr420_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_ARGB_MCU_YCbCr422_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_ARGB_MCU_YCbCr444_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_ARGB_MCU_Gray_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_ARGB_MCU_YCCK_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static void JPEG_Init_MCU_LUT(void); | |
| static void JPEG_InitPreProcColorTables(void); | |
| static uint8_t *JPEG_Set_K_Blocks(uint8_t *pMCUBuffer, uint8_t pKBlocks[16][16], uint32_t ChromaSampling); | |
| #endif /* USE_JPEG_ENCODER == 1 */ | |
| #if (USE_JPEG_DECODER == 1) | |
| static uint32_t JPEG_MCU_YCbCr420_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_MCU_YCbCr422_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_MCU_YCbCr444_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_MCU_Gray_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static uint32_t JPEG_MCU_YCCK_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount); | |
| static void JPEG_InitPostProcColorTables(void); | |
| #endif /* USE_JPEG_DECODER == 1 */ | |
| /** | |
| * @} | |
| */ | |
| /** @defgroup JPEG_Private_Functions JPEG Private Functions | |
| * @{ | |
| */ | |
| #if (USE_JPEG_ENCODER == 1) | |
| /** | |
| * @brief Convert RGB to YCbCr 4:2:0 blocks pixels | |
| * @param pInBuffer : pointer to input RGB888/ARGB8888 frame buffer. | |
| * @param pOutBuffer : pointer to output YCbCr blocks buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from RGB to YCbCr | |
| */ | |
| static uint32_t JPEG_ARGB_MCU_YCbCr420_ConvertBlocks (uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef, colones; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp, offset; | |
| uint32_t red, green, blue; | |
| uint8_t *pOutAddr; | |
| uint8_t *pInAddr; | |
| numberMCU = ((3 * DataCount) / ( 2 * JPEG_BYTES_PER_PIXEL * YCBCR_420_BLOCK_SIZE)); | |
| currentMCU = BlockIndex; | |
| *ConvertedDataCount = numberMCU * JPEG_ConvertorParams.BlockSize; | |
| pOutAddr = &pOutBuffer[0]; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *JPEG_ConvertorParams.H_factor) / JPEG_ConvertorParams.WidthExtend)*JPEG_ConvertorParams.V_factor; | |
| yRef = ((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| if(((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend) == 0) | |
| { | |
| colones = JPEG_ConvertorParams.H_factor - JPEG_ConvertorParams.LineOffset; | |
| } | |
| else | |
| { | |
| colones = JPEG_ConvertorParams.H_factor; | |
| } | |
| offset = 0; | |
| for(i= 0; i < JPEG_ConvertorParams.V_factor; i+=2) | |
| { | |
| pInAddr = &pInBuffer[0] ; | |
| for(j=0; j < colones; j+=2) | |
| { | |
| /* First Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| cbcomp = (int32_t)(*(RED_CB_LUT + red)) + (int32_t)(*(GREEN_CB_LUT + green)) + (int32_t)(*(BLUE_CB_RED_CR_LUT + blue)) + 128; | |
| crcomp = (int32_t)(*(BLUE_CB_RED_CR_LUT + red)) + (int32_t)(*(GREEN_CR_LUT + green)) + (int32_t)(*(BLUE_CR_LUT + blue)) + 128; | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset])) = (ycomp); | |
| (*(pOutAddr + JPEG_ConvertorParams.Cb_MCU_LUT[offset])) = (cbcomp); | |
| (*(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = (crcomp); | |
| /* Second Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + JPEG_BYTES_PER_PIXEL + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + JPEG_BYTES_PER_PIXEL + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + JPEG_BYTES_PER_PIXEL + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset + 1])) = (ycomp); | |
| /* Third Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + JPEG_ConvertorParams.ScaledWidth + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + JPEG_ConvertorParams.ScaledWidth + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + JPEG_ConvertorParams.ScaledWidth + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset + JPEG_ConvertorParams.H_factor])) = (ycomp); | |
| /* Fourth Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_ConvertorParams.ScaledWidth + JPEG_BYTES_PER_PIXEL + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset + JPEG_ConvertorParams.H_factor + 1])) = (ycomp); | |
| /****************/ | |
| pInAddr += JPEG_BYTES_PER_PIXEL * 2; | |
| offset+=2; | |
| } | |
| offset += JPEG_ConvertorParams.H_factor + (JPEG_ConvertorParams.H_factor - colones); | |
| refline += JPEG_ConvertorParams.ScaledWidth * 2 ; | |
| } | |
| pOutAddr += JPEG_ConvertorParams.BlockSize ; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert RGB to YCbCr 4:2:2 blocks pixels | |
| * @param pInBuffer : pointer to input RGB888/ARGB8888 frame buffer. | |
| * @param pOutBuffer : pointer to output YCbCr blocks buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from RGB to YCbCr | |
| */ | |
| static uint32_t JPEG_ARGB_MCU_YCbCr422_ConvertBlocks (uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef, colones; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp, offset; | |
| uint32_t red, green, blue; | |
| uint8_t *pOutAddr; | |
| uint8_t *pInAddr; | |
| numberMCU = ((2 * DataCount) / (JPEG_BYTES_PER_PIXEL * YCBCR_422_BLOCK_SIZE)); | |
| currentMCU = BlockIndex; | |
| *ConvertedDataCount = numberMCU * JPEG_ConvertorParams.BlockSize; | |
| pOutAddr = &pOutBuffer[0]; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *JPEG_ConvertorParams.H_factor) / JPEG_ConvertorParams.WidthExtend)*JPEG_ConvertorParams.V_factor; | |
| yRef = ((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| if(((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend) == 0) | |
| { | |
| colones = JPEG_ConvertorParams.H_factor - JPEG_ConvertorParams.LineOffset; | |
| } | |
| else | |
| { | |
| colones = JPEG_ConvertorParams.H_factor; | |
| } | |
| offset = 0; | |
| for(i= 0; i < JPEG_ConvertorParams.V_factor; i+=1) | |
| { | |
| pInAddr = &pInBuffer[0] ; | |
| for(j=0; j < colones; j+=2) | |
| { | |
| /* First Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| cbcomp = (int32_t)(*(RED_CB_LUT + red)) + (int32_t)(*(GREEN_CB_LUT + green)) + (int32_t)(*(BLUE_CB_RED_CR_LUT + blue)) + 128; | |
| crcomp = (int32_t)(*(BLUE_CB_RED_CR_LUT + red)) + (int32_t)(*(GREEN_CR_LUT + green)) + (int32_t)(*(BLUE_CR_LUT + blue)) + 128; | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset])) = ycomp; | |
| (*(pOutAddr + JPEG_ConvertorParams.Cb_MCU_LUT[offset])) = cbcomp; | |
| (*(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = crcomp; | |
| /* Second Pixel */ | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline + JPEG_BYTES_PER_PIXEL)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BYTES_PER_PIXEL + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset + 1])) = ycomp; | |
| /****************/ | |
| pInAddr += JPEG_BYTES_PER_PIXEL * 2; | |
| offset+=2; | |
| } | |
| offset += (JPEG_ConvertorParams.H_factor - colones); | |
| refline += JPEG_ConvertorParams.ScaledWidth ; | |
| } | |
| pOutAddr += JPEG_ConvertorParams.BlockSize; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert RGB to YCbCr 4:4:4 blocks pixels | |
| * @param pInBuffer : pointer to input RGB888/ARGB8888 frame buffer. | |
| * @param pOutBuffer : pointer to output YCbCr blocks buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from RGB to YCbCr | |
| */ | |
| static uint32_t JPEG_ARGB_MCU_YCbCr444_ConvertBlocks (uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef, colones; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp, offset; | |
| uint32_t red, green, blue; | |
| uint8_t *pOutAddr; | |
| uint8_t *pInAddr; | |
| numberMCU = ((3 * DataCount) / (JPEG_BYTES_PER_PIXEL * YCBCR_444_BLOCK_SIZE)); | |
| currentMCU = BlockIndex; | |
| *ConvertedDataCount = numberMCU * JPEG_ConvertorParams.BlockSize; | |
| pOutAddr = &pOutBuffer[0]; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *JPEG_ConvertorParams.H_factor) / JPEG_ConvertorParams.WidthExtend)*JPEG_ConvertorParams.V_factor; | |
| yRef = ((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| if(((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend) == 0) | |
| { | |
| colones = JPEG_ConvertorParams.H_factor - JPEG_ConvertorParams.LineOffset; | |
| } | |
| else | |
| { | |
| colones = JPEG_ConvertorParams.H_factor; | |
| } | |
| offset = 0; | |
| for(i= 0; i < JPEG_ConvertorParams.V_factor; i++) | |
| { | |
| pInAddr = &pInBuffer[0] ; | |
| for(j=0; j < colones; j++) | |
| { | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue)); | |
| cbcomp = (int32_t)(*(RED_CB_LUT + red)) + (int32_t)(*(GREEN_CB_LUT + green)) + (int32_t)(*(BLUE_CB_RED_CR_LUT + blue)) + 128; | |
| crcomp = (int32_t)(*(BLUE_CB_RED_CR_LUT + red)) + (int32_t)(*(GREEN_CR_LUT + green)) + (int32_t)(*(BLUE_CR_LUT + blue)) + 128; | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset])) = (ycomp); | |
| (*(pOutAddr + JPEG_ConvertorParams.Cb_MCU_LUT[offset])) = (cbcomp); | |
| (*(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = (crcomp); | |
| pInAddr += JPEG_BYTES_PER_PIXEL; | |
| offset++; | |
| } | |
| offset += (JPEG_ConvertorParams.H_factor - colones); | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| pOutAddr += JPEG_ConvertorParams.BlockSize; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert RGB to Gray blocks pixels | |
| * @param pInBuffer : pointer to input RGB888/ARGB8888 blocks. | |
| * @param pOutBuffer : pointer to output Gray blocks buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from RGB to Gray | |
| */ | |
| static uint32_t JPEG_ARGB_MCU_Gray_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef, colones; | |
| uint32_t refline; | |
| int32_t offset; | |
| uint32_t red, green, blue; | |
| uint8_t *pOutAddr; | |
| uint8_t *pInAddr; | |
| uint8_t ycomp; | |
| numberMCU = (DataCount / (JPEG_BYTES_PER_PIXEL * GRAY_444_BLOCK_SIZE)); | |
| currentMCU = BlockIndex; | |
| *ConvertedDataCount = numberMCU * GRAY_444_BLOCK_SIZE; | |
| pOutAddr = &pOutBuffer[0]; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *JPEG_ConvertorParams.H_factor) / JPEG_ConvertorParams.WidthExtend)*JPEG_ConvertorParams.V_factor; | |
| yRef = ((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| if(((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend) == 0) | |
| { | |
| colones = JPEG_ConvertorParams.H_factor - JPEG_ConvertorParams.LineOffset; | |
| } | |
| else | |
| { | |
| colones = JPEG_ConvertorParams.H_factor; | |
| } | |
| offset = 0; | |
| for(i= 0; i < JPEG_ConvertorParams.V_factor; i++) | |
| { | |
| pInAddr = &pInBuffer[0] ; | |
| for(j=0; j < colones; j++) | |
| { | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + refline + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + refline + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + refline + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| ycomp = (uint8_t)((int32_t)(*(RED_Y_LUT + red)) + (int32_t)(*(GREEN_Y_LUT + green)) + (int32_t)(*(BLUE_Y_LUT + blue))); | |
| (*(pOutAddr + offset)) = (ycomp); | |
| pInAddr += JPEG_BYTES_PER_PIXEL; | |
| offset++; | |
| } | |
| offset += (JPEG_ConvertorParams.H_factor - colones); | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| pOutAddr += JPEG_ConvertorParams.BlockSize; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert RGB to YCCK blocks pixels | |
| * @param pInBuffer : pointer to input RGB888/ARGB8888 blocks. | |
| * @param pOutBuffer : pointer to output YCCK blocks buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from RGB to YCCK | |
| */ | |
| static uint32_t JPEG_ARGB_MCU_YCCK_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef, colones; | |
| uint32_t refline; | |
| uint32_t offset; | |
| int32_t red, green, blue, color_k ; | |
| uint8_t *pOutAddr; | |
| uint8_t *pInAddr; | |
| numberMCU = ((3 * DataCount) / (JPEG_BYTES_PER_PIXEL * CMYK_444_BLOCK_SIZE)); | |
| *ConvertedDataCount = numberMCU * CMYK_444_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| pOutAddr = &pOutBuffer[0]; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *JPEG_ConvertorParams.H_factor) / JPEG_ConvertorParams.WidthExtend)*JPEG_ConvertorParams.V_factor; | |
| yRef = ((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| if(((currentMCU *JPEG_ConvertorParams.H_factor) % JPEG_ConvertorParams.WidthExtend) == 0) | |
| { | |
| colones = JPEG_ConvertorParams.H_factor - JPEG_ConvertorParams.LineOffset; | |
| } | |
| else | |
| { | |
| colones = JPEG_ConvertorParams.H_factor; | |
| } | |
| offset = 0; | |
| for(i= 0; i < JPEG_ConvertorParams.V_factor; i++) | |
| { | |
| pInAddr = &pInBuffer[refline]; | |
| for(j=0; j < colones; j++) | |
| { | |
| #if (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| red = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_RED_MASK) >> JPEG_RED_OFFSET) ; | |
| green = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_GREEN_MASK) >> JPEG_GREEN_OFFSET) ; | |
| blue = (((*(__IO uint16_t *)(pInAddr + refline)) & JPEG_RGB565_BLUE_MASK) >> JPEG_BLUE_OFFSET) ; | |
| red = (red << 3) | (red >> 2); | |
| green = (green << 2) | (green >> 4); | |
| blue = (blue << 3) | (blue >> 2); | |
| #else | |
| red = (*(pInAddr + JPEG_RED_OFFSET/8)) ; | |
| green = (*(pInAddr + JPEG_GREEN_OFFSET/8)) ; | |
| blue = (*(pInAddr + JPEG_BLUE_OFFSET/8)) ; | |
| #endif | |
| color_k = MAX(MAX(red,green),blue); | |
| kBlocks[i][j]=color_k; | |
| (*(pOutAddr + JPEG_ConvertorParams.Y_MCU_LUT[offset])) = red * 255 / color_k; | |
| (*(pOutAddr + JPEG_ConvertorParams.Cb_MCU_LUT[offset])) = green * 255 / color_k; | |
| (*(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = blue * 255 / color_k; | |
| pInAddr += JPEG_BYTES_PER_PIXEL; | |
| offset++; | |
| } | |
| offset += (JPEG_ConvertorParams.H_factor - colones); | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| JPEG_Set_K_Blocks(pOutAddr, kBlocks, JPEG_ConvertorParams.ChromaSubsampling); | |
| pOutAddr += JPEG_ConvertorParams.BlockSize; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Retrive Encoding RGB to YCbCr color conversion function and block number | |
| * @param pJpegInfo : JPEG_ConfTypeDef that contains the JPEG image informations. | |
| * These info are available in the HAL callback "HAL_JPEG_InfoReadyCallback". | |
| * @param pFunction : pointer to JPEG_RGBToYCbCr_Convert_Function , used to retrive the color conversion function | |
| * depending of the jpeg image color space and chroma sampling info. | |
| * @param ImageNbMCUs : pointer to uint32_t, used to retrive the total number of MCU blocks in the jpeg image. | |
| * @retval HAL status : HAL_OK or HAL_ERROR. | |
| */ | |
| HAL_StatusTypeDef JPEG_GetEncodeColorConvertFunc(JPEG_ConfTypeDef *pJpegInfo, JPEG_RGBToYCbCr_Convert_Function *pFunction, uint32_t *ImageNbMCUs) | |
| { | |
| uint32_t hMCU, vMCU; | |
| JPEG_ConvertorParams.ColorSpace = pJpegInfo->ColorSpace; | |
| JPEG_ConvertorParams.ChromaSubsampling = pJpegInfo->ChromaSubsampling; | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_YCBCR_COLORSPACE) | |
| { | |
| if(JPEG_ConvertorParams.ChromaSubsampling == JPEG_420_SUBSAMPLING) | |
| { | |
| *pFunction = JPEG_ARGB_MCU_YCbCr420_ConvertBlocks; | |
| } | |
| else if (JPEG_ConvertorParams.ChromaSubsampling == JPEG_422_SUBSAMPLING) | |
| { | |
| *pFunction = JPEG_ARGB_MCU_YCbCr422_ConvertBlocks; | |
| } | |
| else if (JPEG_ConvertorParams.ChromaSubsampling == JPEG_444_SUBSAMPLING) | |
| { | |
| *pFunction = JPEG_ARGB_MCU_YCbCr444_ConvertBlocks; | |
| } | |
| else | |
| { | |
| return HAL_ERROR; /* Chroma SubSampling Not supported*/ | |
| } | |
| } | |
| else if(JPEG_ConvertorParams.ColorSpace == JPEG_GRAYSCALE_COLORSPACE) | |
| { | |
| *pFunction = JPEG_ARGB_MCU_Gray_ConvertBlocks; | |
| } | |
| else if(JPEG_ConvertorParams.ColorSpace == JPEG_CMYK_COLORSPACE) | |
| { | |
| *pFunction = JPEG_ARGB_MCU_YCCK_ConvertBlocks; | |
| } | |
| else | |
| { | |
| return HAL_ERROR; /* Color space Not supported*/ | |
| } | |
| JPEG_ConvertorParams.ImageWidth = pJpegInfo->ImageWidth; | |
| JPEG_ConvertorParams.ImageHeight = pJpegInfo->ImageHeight; | |
| JPEG_ConvertorParams.ImageSize_Bytes = pJpegInfo->ImageWidth * pJpegInfo->ImageHeight * JPEG_BYTES_PER_PIXEL; | |
| if((JPEG_ConvertorParams.ChromaSubsampling == JPEG_420_SUBSAMPLING) || (JPEG_ConvertorParams.ChromaSubsampling == JPEG_422_SUBSAMPLING)) | |
| { | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 16; | |
| JPEG_ConvertorParams.Y_MCU_LUT = JPEG_Y_MCU_LUT; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 16 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 16; | |
| if(JPEG_ConvertorParams.ChromaSubsampling == JPEG_420_SUBSAMPLING) | |
| { | |
| JPEG_ConvertorParams.V_factor = 16; | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_YCBCR_COLORSPACE) | |
| { | |
| JPEG_ConvertorParams.BlockSize = YCBCR_420_BLOCK_SIZE; | |
| } | |
| JPEG_ConvertorParams.Cb_MCU_LUT = JPEG_Cb_MCU_420_LUT; | |
| JPEG_ConvertorParams.Cr_MCU_LUT = JPEG_Cr_MCU_420_LUT; | |
| JPEG_ConvertorParams.K_MCU_LUT = JPEG_K_MCU_420_LUT; | |
| } | |
| else /* 4:2:2*/ | |
| { | |
| JPEG_ConvertorParams.V_factor = 8; | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_YCBCR_COLORSPACE) | |
| { | |
| JPEG_ConvertorParams.BlockSize = YCBCR_422_BLOCK_SIZE; | |
| } | |
| JPEG_ConvertorParams.Cb_MCU_LUT = JPEG_Cb_MCU_422_LUT; | |
| JPEG_ConvertorParams.Cr_MCU_LUT = JPEG_Cr_MCU_422_LUT; | |
| JPEG_ConvertorParams.K_MCU_LUT = JPEG_K_MCU_422_LUT; | |
| } | |
| } | |
| else if(JPEG_ConvertorParams.ChromaSubsampling == JPEG_444_SUBSAMPLING) | |
| { | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 8; | |
| JPEG_ConvertorParams.Y_MCU_LUT = JPEG_Y_MCU_444_LUT; | |
| JPEG_ConvertorParams.Cb_MCU_LUT = JPEG_Cb_MCU_444_LUT; | |
| JPEG_ConvertorParams.Cr_MCU_LUT = JPEG_Cr_MCU_444_LUT; | |
| JPEG_ConvertorParams.K_MCU_LUT = JPEG_K_MCU_444_LUT; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 8 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 8; | |
| JPEG_ConvertorParams.V_factor = 8; | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_YCBCR_COLORSPACE) | |
| { | |
| JPEG_ConvertorParams.BlockSize = YCBCR_444_BLOCK_SIZE; | |
| } | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_CMYK_COLORSPACE) | |
| { | |
| JPEG_ConvertorParams.BlockSize = CMYK_444_BLOCK_SIZE; | |
| } | |
| else if(JPEG_ConvertorParams.ColorSpace == JPEG_GRAYSCALE_COLORSPACE) | |
| { | |
| JPEG_ConvertorParams.BlockSize = GRAY_444_BLOCK_SIZE; | |
| } | |
| } | |
| else | |
| { | |
| return HAL_ERROR; /* Not supported*/ | |
| } | |
| JPEG_ConvertorParams.WidthExtend = JPEG_ConvertorParams.ImageWidth + JPEG_ConvertorParams.LineOffset; | |
| JPEG_ConvertorParams.ScaledWidth = JPEG_BYTES_PER_PIXEL * JPEG_ConvertorParams.ImageWidth; | |
| hMCU = (JPEG_ConvertorParams.ImageWidth / JPEG_ConvertorParams.H_factor); | |
| if((JPEG_ConvertorParams.ImageWidth % JPEG_ConvertorParams.H_factor) != 0) | |
| { | |
| hMCU++; /*+1 for horizenatl incomplete MCU */ | |
| } | |
| vMCU = (JPEG_ConvertorParams.ImageHeight / JPEG_ConvertorParams.V_factor); | |
| if((JPEG_ConvertorParams.ImageHeight % JPEG_ConvertorParams.V_factor) != 0) | |
| { | |
| vMCU++; /*+1 for vertical incomplete MCU */ | |
| } | |
| JPEG_ConvertorParams.MCU_Total_Nb = (hMCU * vMCU); | |
| *ImageNbMCUs = JPEG_ConvertorParams.MCU_Total_Nb; | |
| return HAL_OK; | |
| } | |
| #endif /* USE_JPEG_ENCODER == 1 */ | |
| #if (USE_JPEG_DECODER == 1) | |
| /** | |
| * @brief Convert YCbCr 4:2:0 blocks to RGB pixels | |
| * @param pInBuffer : pointer to input YCbCr blocks buffer. | |
| * @param pOutBuffer : pointer to output RGB888/ARGB8888 frame buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from YCbCr to RGB | |
| */ | |
| static uint32_t JPEG_MCU_YCbCr420_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j,k, currentMCU, xRef,yRef; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp; | |
| int32_t c_red, c_blue, c_green; | |
| uint8_t *pOutAddr, *pOutAddr2; | |
| uint8_t *pChrom, *pLum; | |
| numberMCU = DataCount / YCBCR_420_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *16) / JPEG_ConvertorParams.WidthExtend)*16; | |
| yRef = ((currentMCU *16) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| pChrom = pInBuffer + 256; /* pChroma = pInBuffer + 4*64 */ | |
| pLum = pInBuffer; | |
| for(i= 0; i < 16; i+=2) | |
| { | |
| if(i == 8) | |
| { | |
| pLum = pInBuffer + 128; | |
| } | |
| if(refline < JPEG_ConvertorParams.ImageSize_Bytes) | |
| { | |
| pOutAddr = pOutBuffer + refline; | |
| pOutAddr2 = pOutAddr + JPEG_ConvertorParams.ScaledWidth; | |
| for(k= 0; k<2; k++) | |
| { | |
| for(j=0; j < 8; j+=2) | |
| { | |
| cbcomp = (int32_t)(*(pChrom)); | |
| c_blue = (int32_t)(*(CB_BLUE_LUT + cbcomp)); | |
| crcomp = (int32_t)(*(pChrom + 64)); | |
| c_red = (int32_t)(*(CR_RED_LUT + crcomp)); | |
| c_green = ((int32_t)(*(CR_GREEN_LUT + crcomp)) + (int32_t)(*(CB_GREEN_LUT + cbcomp))) >> 16; | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint32_t *)pOutAddr = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| *((__IO uint32_t *)(pOutAddr + 4)) = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8)); | |
| *(__IO uint32_t *)pOutAddr2 = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8 +1)); | |
| *((__IO uint32_t *)(pOutAddr2 +4)) = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| pOutAddr[JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr[JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr[JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| pOutAddr[3 + JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr[3 + JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr[3 + JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8)); | |
| pOutAddr2[JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr2[JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr2[JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8 +1)); | |
| pOutAddr2[3+ JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr2[3 + JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr2[3 + JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint16_t *)pOutAddr = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| *((__IO uint16_t *)(pOutAddr + 2)) = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8)); | |
| *(__IO uint16_t *)pOutAddr2 = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +8 +1)); | |
| *((__IO uint16_t *)(pOutAddr2 +2)) = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| #endif /* JPEG_RGB_FORMAT */ | |
| pOutAddr += JPEG_BYTES_PER_PIXEL * 2; | |
| pOutAddr2 += JPEG_BYTES_PER_PIXEL * 2; | |
| pChrom++; | |
| } | |
| pLum += 64; | |
| } | |
| pLum = pLum - 128 + 16; | |
| refline += 2*JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| } | |
| pInBuffer += YCBCR_420_BLOCK_SIZE; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert YCbCr 4:2:2 blocks to RGB pixels | |
| * @param pInBuffer : pointer to input YCbCr blocks buffer. | |
| * @param pOutBuffer : pointer to output RGB888/ARGB8888 frame buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from YCbCr to RGB | |
| */ | |
| static uint32_t JPEG_MCU_YCbCr422_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j,k, currentMCU, xRef,yRef; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp; | |
| int32_t c_red, c_blue, c_green; | |
| uint8_t *pOutAddr; | |
| uint8_t *pChrom, *pLum; | |
| numberMCU = DataCount / YCBCR_422_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *16) / JPEG_ConvertorParams.WidthExtend)*8; | |
| yRef = ((currentMCU *16) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| pChrom = pInBuffer + 128; /* pChroma = pInBuffer + 2*64 */ | |
| pLum = pInBuffer; | |
| for(i= 0; i < 8; i++) | |
| { | |
| if(refline < JPEG_ConvertorParams.ImageSize_Bytes) | |
| { | |
| pOutAddr = pOutBuffer + refline; | |
| for(k= 0; k<2; k++) | |
| { | |
| for(j=0; j < 8; j+=2) | |
| { | |
| cbcomp = (int32_t)(*(pChrom)); | |
| c_blue = (int32_t)(*(CB_BLUE_LUT + cbcomp)); | |
| crcomp = (int32_t)(*(pChrom + 64)); | |
| c_red = (int32_t)(*(CR_RED_LUT + crcomp)); | |
| c_green = ((int32_t)(*(CR_GREEN_LUT + crcomp)) + (int32_t)(*(CB_GREEN_LUT + cbcomp))) >> 16; | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint32_t *)pOutAddr = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| *((__IO uint32_t *)(pOutAddr + 4)) = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| pOutAddr[JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr[JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr[JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| pOutAddr[3 + JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr[3 + JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr[3 + JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint16_t *)pOutAddr = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| /**********/ | |
| ycomp = (int32_t)(*(pLum +j +1)); | |
| *((__IO uint16_t *)(pOutAddr + 2)) = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| #endif /* JPEG_RGB_FORMAT*/ | |
| pOutAddr += JPEG_BYTES_PER_PIXEL * 2; | |
| pChrom++; | |
| } | |
| pLum += 64; | |
| } | |
| pLum = pLum - 128 + 8; | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| } | |
| pInBuffer += YCBCR_422_BLOCK_SIZE; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert YCbCr 4:4:4 blocks to RGB pixels | |
| * @param pInBuffer : pointer to input YCbCr blocks buffer. | |
| * @param pOutBuffer : pointer to output RGB888/ARGB8888 frame buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from YCbCr to RGB | |
| */ | |
| static uint32_t JPEG_MCU_YCbCr444_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef; | |
| uint32_t refline; | |
| int32_t ycomp, crcomp, cbcomp; | |
| int32_t c_red, c_blue, c_green; | |
| uint8_t *pOutAddr; | |
| uint8_t *pChrom, *pLum; | |
| numberMCU = DataCount / YCBCR_444_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *8) / JPEG_ConvertorParams.WidthExtend)*8; | |
| yRef = ((currentMCU *8) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| pChrom = pInBuffer + 64; /* pChroma = pInBuffer + 4*64 */ | |
| pLum = pInBuffer; | |
| for(i= 0; i < 8; i++) | |
| { | |
| if(refline < JPEG_ConvertorParams.ImageSize_Bytes) | |
| { | |
| pOutAddr = pOutBuffer+ refline; | |
| for(j=0; j < 8; j++) | |
| { | |
| cbcomp = (int32_t)(*pChrom); | |
| c_blue = (int32_t)(*(CB_BLUE_LUT + cbcomp)); | |
| crcomp = (int32_t)(*(pChrom + 64)); | |
| c_red = (int32_t)(*(CR_RED_LUT + crcomp)); | |
| c_green = ((int32_t)(*(CR_GREEN_LUT + crcomp)) + (int32_t)(*(CB_GREEN_LUT + cbcomp))) >> 16; | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint32_t *)pOutAddr = | |
| (CLAMP(ycomp + c_red) << JPEG_RED_OFFSET) | \ | |
| (CLAMP( ycomp + c_green) << JPEG_GREEN_OFFSET) | \ | |
| (CLAMP(ycomp + c_blue) << JPEG_BLUE_OFFSET); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB888) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| pOutAddr[JPEG_RED_OFFSET/8] = CLAMP(ycomp + c_red); | |
| pOutAddr[JPEG_GREEN_OFFSET/8] = CLAMP(ycomp + c_green); | |
| pOutAddr[JPEG_BLUE_OFFSET/8] = CLAMP(ycomp + c_blue); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| ycomp = (int32_t)(*(pLum +j)); | |
| *(__IO uint16_t *)pOutAddr = | |
| ((CLAMP(ycomp + c_red) >> 3) << JPEG_RED_OFFSET) | \ | |
| ((CLAMP( ycomp + c_green) >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((CLAMP(ycomp + c_blue) >> 3) << JPEG_BLUE_OFFSET); | |
| #endif /* JPEG_RGB_FORMAT */ | |
| pOutAddr += JPEG_BYTES_PER_PIXEL; | |
| pChrom++; | |
| } | |
| pLum += 8; | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| } | |
| pInBuffer += YCBCR_444_BLOCK_SIZE; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert Y Gray blocks to RGB pixels | |
| * @param pInBuffer : pointer to input Luminance Y blocks buffer. | |
| * @param pOutBuffer : pointer to output RGB888/ARGB8888 frame buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from YCbCr to RGB | |
| */ | |
| static uint32_t JPEG_MCU_Gray_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t currentMCU, xRef,yRef; | |
| uint32_t refline; | |
| uint32_t i,j, ySample; | |
| uint8_t *pOutAddr, *pLum; | |
| numberMCU = DataCount / GRAY_444_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *8) / JPEG_ConvertorParams.WidthExtend)*8; | |
| yRef = ((currentMCU *8) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| pLum = pInBuffer; | |
| for(i= 0; i < 8; i++) | |
| { | |
| pOutAddr = pOutBuffer + refline; | |
| if(refline < JPEG_ConvertorParams.ImageSize_Bytes) | |
| { | |
| for(j=0; j < 8; j++) | |
| { | |
| ySample = (uint32_t)(*pLum); | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| *(__IO uint32_t *)pOutAddr = ySample | (ySample << 8) | (ySample << 16); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB888) | |
| pOutAddr[0] = ySample; | |
| pOutAddr[1] = ySample; | |
| pOutAddr[2] = ySample; | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| *(__IO uint16_t *)pOutAddr = ((ySample >> 3) << 11) | ((ySample >> 2) << 5) | (ySample >> 3); | |
| #endif /* JPEG_RGB_FORMAT */ | |
| pOutAddr += JPEG_BYTES_PER_PIXEL; | |
| pLum++; | |
| } | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| } | |
| pInBuffer += GRAY_444_BLOCK_SIZE; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Convert CMYK blocks to RGB pixels | |
| * @param pInBuffer : pointer to input CMYK blocks buffer. | |
| * @param pOutBuffer : pointer to output RGB888/ARGB8888 frame buffer. | |
| * @param BlockIndex : index of the input buffer first block in the final image. | |
| * @param DataCount : number of bytes in the input buffer . | |
| * @param ConvertedDataCount : number of converted bytes from input buffer. | |
| * @retval Number of blcoks converted from CMYK to RGB | |
| */ | |
| static uint32_t JPEG_MCU_YCCK_ARGB_ConvertBlocks(uint8_t *pInBuffer, | |
| uint8_t *pOutBuffer, | |
| uint32_t BlockIndex, | |
| uint32_t DataCount, | |
| uint32_t *ConvertedDataCount) | |
| { | |
| uint32_t numberMCU; | |
| uint32_t i,j, currentMCU, xRef,yRef; | |
| uint32_t refline; | |
| int32_t color_k; | |
| int32_t c_red, c_blue, c_green; | |
| uint8_t *pOutAddr, *pChrom; | |
| numberMCU = DataCount / CMYK_444_BLOCK_SIZE; | |
| currentMCU = BlockIndex; | |
| while(currentMCU < (numberMCU + BlockIndex)) | |
| { | |
| xRef = ((currentMCU *8) / JPEG_ConvertorParams.WidthExtend)*8; | |
| yRef = ((currentMCU *8) % JPEG_ConvertorParams.WidthExtend); | |
| refline = JPEG_ConvertorParams.ScaledWidth * xRef + (JPEG_BYTES_PER_PIXEL*yRef); | |
| currentMCU++; | |
| pChrom = pInBuffer; | |
| for(i= 0; i < 8; i++) | |
| { | |
| if(refline < JPEG_ConvertorParams.ImageSize_Bytes) | |
| { | |
| pOutAddr = pOutBuffer+ refline; | |
| for(j=0; j < 8; j++) | |
| { | |
| color_k = (int32_t)(*(pChrom + 192)); | |
| c_red = (color_k * ((int32_t)(*pChrom)))/255; | |
| c_green = (color_k * (int32_t)(*(pChrom + 64)))/255; | |
| c_blue = (color_k * (int32_t)(*(pChrom + 128)))/255; | |
| #if (JPEG_RGB_FORMAT == JPEG_ARGB8888) | |
| *(__IO uint32_t *)pOutAddr = | |
| (c_red << JPEG_RED_OFFSET) | \ | |
| (c_green << JPEG_GREEN_OFFSET) | \ | |
| (c_blue << JPEG_BLUE_OFFSET); | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB888) | |
| pOutAddr[JPEG_RED_OFFSET/8] = c_red; | |
| pOutAddr[JPEG_GREEN_OFFSET/8] = c_green; | |
| pOutAddr[JPEG_BLUE_OFFSET/8] = c_blue; | |
| #elif (JPEG_RGB_FORMAT == JPEG_RGB565) | |
| *(__IO uint16_t *)pOutAddr = | |
| ((c_red >> 3) << JPEG_RED_OFFSET) | \ | |
| ((c_green >> 2) << JPEG_GREEN_OFFSET) | \ | |
| ((c_blue >> 3) << JPEG_BLUE_OFFSET); | |
| #endif /* JPEG_RGB_FORMAT */ | |
| pOutAddr += JPEG_BYTES_PER_PIXEL; | |
| pChrom++; | |
| } | |
| refline += JPEG_ConvertorParams.ScaledWidth; | |
| } | |
| } | |
| pInBuffer += CMYK_444_BLOCK_SIZE; | |
| } | |
| return numberMCU; | |
| } | |
| /** | |
| * @brief Retrive Decoding YCbCr to RGB color conversion function and block number | |
| * @param pJpegInfo : JPEG_ConfTypeDef that contains the JPEG image informations. | |
| * These info are available in the HAL callback "HAL_JPEG_InfoReadyCallback". | |
| * @param pFunction : pointer to JPEG_YCbCrToRGB_Convert_Function , used to retrive the color conversion function | |
| * depending of the jpeg image color space and chroma sampling info. | |
| * @param ImageNbMCUs : pointer to uint32_t, used to retrive the total number of MCU blocks in the jpeg image. | |
| * @retval HAL status : HAL_OK or HAL_ERROR. | |
| */ | |
| HAL_StatusTypeDef JPEG_GetDecodeColorConvertFunc(JPEG_ConfTypeDef *pJpegInfo, JPEG_YCbCrToRGB_Convert_Function *pFunction, uint32_t *ImageNbMCUs) | |
| { | |
| uint32_t hMCU, vMCU; | |
| JPEG_ConvertorParams.ColorSpace = pJpegInfo->ColorSpace; | |
| JPEG_ConvertorParams.ImageWidth = pJpegInfo->ImageWidth; | |
| JPEG_ConvertorParams.ImageHeight = pJpegInfo->ImageHeight; | |
| JPEG_ConvertorParams.ImageSize_Bytes = pJpegInfo->ImageWidth * pJpegInfo->ImageHeight * JPEG_BYTES_PER_PIXEL; | |
| JPEG_ConvertorParams.ChromaSubsampling = pJpegInfo->ChromaSubsampling; | |
| if(JPEG_ConvertorParams.ColorSpace == JPEG_YCBCR_COLORSPACE) | |
| { | |
| if(JPEG_ConvertorParams.ChromaSubsampling == JPEG_420_SUBSAMPLING) | |
| { | |
| *pFunction = JPEG_MCU_YCbCr420_ARGB_ConvertBlocks; | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 16; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 16 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 16; | |
| JPEG_ConvertorParams.V_factor = 16; | |
| } | |
| else if(JPEG_ConvertorParams.ChromaSubsampling == JPEG_422_SUBSAMPLING) | |
| { | |
| *pFunction = JPEG_MCU_YCbCr422_ARGB_ConvertBlocks; | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 16; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 16 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 16; | |
| JPEG_ConvertorParams.V_factor = 8; | |
| } | |
| else /*4:4:4*/ | |
| { | |
| *pFunction = JPEG_MCU_YCbCr444_ARGB_ConvertBlocks; | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 8; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 8 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 8; | |
| JPEG_ConvertorParams.V_factor = 8; | |
| } | |
| } | |
| else if(JPEG_ConvertorParams.ColorSpace == JPEG_GRAYSCALE_COLORSPACE) | |
| { | |
| *pFunction = JPEG_MCU_Gray_ARGB_ConvertBlocks; | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 8; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 8 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 8; | |
| JPEG_ConvertorParams.V_factor = 8; | |
| } | |
| else if(JPEG_ConvertorParams.ColorSpace == JPEG_CMYK_COLORSPACE) | |
| { | |
| *pFunction = JPEG_MCU_YCCK_ARGB_ConvertBlocks; | |
| JPEG_ConvertorParams.LineOffset = JPEG_ConvertorParams.ImageWidth % 8; | |
| if(JPEG_ConvertorParams.LineOffset != 0) | |
| { | |
| JPEG_ConvertorParams.LineOffset = 8 - JPEG_ConvertorParams.LineOffset; | |
| } | |
| JPEG_ConvertorParams.H_factor = 8; | |
| JPEG_ConvertorParams.V_factor = 8; | |
| } | |
| else | |
| { | |
| return HAL_ERROR; /* Color space Not supported*/ | |
| } | |
| JPEG_ConvertorParams.WidthExtend = JPEG_ConvertorParams.ImageWidth + JPEG_ConvertorParams.LineOffset; | |
| JPEG_ConvertorParams.ScaledWidth = JPEG_BYTES_PER_PIXEL * JPEG_ConvertorParams.ImageWidth; | |
| hMCU = (JPEG_ConvertorParams.ImageWidth / JPEG_ConvertorParams.H_factor); | |
| if((JPEG_ConvertorParams.ImageWidth % JPEG_ConvertorParams.H_factor) != 0) | |
| { | |
| hMCU++; /*+1 for horizenatl incomplete MCU */ | |
| } | |
| vMCU = (JPEG_ConvertorParams.ImageHeight / JPEG_ConvertorParams.V_factor); | |
| if((JPEG_ConvertorParams.ImageHeight % JPEG_ConvertorParams.V_factor) != 0) | |
| { | |
| vMCU++; /*+1 for vertical incomplete MCU */ | |
| } | |
| JPEG_ConvertorParams.MCU_Total_Nb = (hMCU * vMCU); | |
| *ImageNbMCUs = JPEG_ConvertorParams.MCU_Total_Nb; | |
| return HAL_OK; | |
| } | |
| /** | |
| * @brief Initializes the YCbCr -> RGB colors conversion Look Up Tables | |
| * @param None | |
| * @retval None | |
| */ | |
| void JPEG_InitPostProcColorTables(void) | |
| { | |
| int32_t index, i; | |
| for (i = 0; i <= 255; i++) | |
| { | |
| index = (i * 2) - 256; | |
| CR_RED_LUT[i] = ( (((int32_t) ((1.40200 / 2) * (1L << 16))) * index) + ((int32_t) 1 << (16 - 1))) >> 16; | |
| CB_BLUE_LUT[i] = ( (((int32_t) ((1.77200 / 2) * (1L << 16))) * index) + ((int32_t) 1 << (16 - 1))) >> 16; | |
| CR_GREEN_LUT[i] = (-((int32_t) ((0.71414 / 2) * (1L << 16)))) * index; | |
| CB_GREEN_LUT[i] = (-((int32_t) ((0.34414 / 2) * (1L << 16)))) * index; | |
| } | |
| } | |
| #endif /* USE_JPEG_DECODER == 1 */ | |
| /** | |
| * @brief Initializes the colors conversion Look Up Tables | |
| * @param None | |
| * @retval None | |
| */ | |
| void JPEG_InitColorTables(void) | |
| { | |
| #if (USE_JPEG_ENCODER == 1) | |
| JPEG_InitPreProcColorTables(); | |
| JPEG_Init_MCU_LUT(); | |
| #endif | |
| #if (USE_JPEG_DECODER == 1) | |
| JPEG_InitPostProcColorTables(); | |
| #endif | |
| } | |
| #if (USE_JPEG_ENCODER == 1) | |
| /** | |
| * @brief Initializes the RGB -> YCbCr colors conversion Look Up Tables | |
| * @param None | |
| * @retval None | |
| */ | |
| void JPEG_InitPreProcColorTables(void) | |
| { | |
| int32_t i; | |
| for (i = 0; i <= 255; i++) | |
| { | |
| RED_Y_LUT[i] = (( ((int32_t) ((0.299 ) * (1L << 16))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| GREEN_Y_LUT[i] = (( ((int32_t) ((0.587 ) * (1L << 16))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| BLUE_Y_LUT[i] = (( ((int32_t) ((0.114 ) * (1L << 16))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| RED_CB_LUT[i] = (((-((int32_t) ((0.1687 ) * (1L << 16)))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| GREEN_CB_LUT[i] = (((-((int32_t) ((0.3313 ) * (1L << 16)))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| /* BLUE_CB_LUT and RED_CR_LUT are identical */ | |
| BLUE_CB_RED_CR_LUT[i] = (( ((int32_t) ((0.5 ) * (1L << 16))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| GREEN_CR_LUT[i] = (((-((int32_t) ((0.4187 ) * (1L << 16)))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| BLUE_CR_LUT[i] = (((-((int32_t) ((0.0813 ) * (1L << 16)))) * i) + ((int32_t) 1 << (16 - 1))) >> 16 ; | |
| } | |
| } | |
| /** | |
| * @brief Initializes the MCU Look Up Tables | |
| * @param None | |
| * @retval None | |
| */ | |
| void JPEG_Init_MCU_LUT(void) | |
| { | |
| uint32_t i, j, offset; | |
| /*Y LUT */ | |
| for(i = 0; i < 16; i++) | |
| { | |
| for(j = 0; j < 16; j++) | |
| { | |
| offset = j + (i*8); | |
| if((j>=8) && (i>=8)) offset+= 120; | |
| else if((j>=8) && (i<8)) offset+= 56; | |
| else if((j<8) && (i>=8)) offset+= 64; | |
| JPEG_Y_MCU_LUT[i*16 + j] = offset; | |
| } | |
| } | |
| /*Cb Cr K LUT*/ | |
| for(i = 0; i < 16; i++) | |
| { | |
| for(j = 0; j < 16; j++) | |
| { | |
| offset = i*16 + j; | |
| JPEG_Cb_MCU_420_LUT[offset] = (j/2) + ((i/2)*8) + 256; | |
| JPEG_Cb_MCU_422_LUT[offset] = (j/2) + (i*8) + 128; | |
| JPEG_Cr_MCU_420_LUT[offset] = (j/2) + ((i/2)*8) + 320; | |
| JPEG_Cr_MCU_422_LUT[offset] = (j/2) + (i*8) + 192; | |
| JPEG_K_MCU_420_LUT[offset] = (j/2) + ((i/2)*8) + 384; | |
| JPEG_K_MCU_422_LUT[offset] = (j/2) + ((i/2)*8) + 256; | |
| } | |
| } | |
| for(i = 0; i < 8; i++) | |
| { | |
| for(j = 0; j < 8; j++) | |
| { | |
| offset = i*8 + j; | |
| JPEG_Y_MCU_444_LUT[offset] = offset; | |
| JPEG_Cb_MCU_444_LUT[offset] = offset + 64 ; | |
| JPEG_Cr_MCU_444_LUT[offset] = offset + 128 ; | |
| JPEG_K_MCU_444_LUT[offset] = offset + 192 ; | |
| } | |
| } | |
| } | |
| /** | |
| * @brief Initializes the YCCK format K Blocks | |
| * @param ChromaSampling | |
| * @retval pMCUBuffer | |
| */ | |
| static uint8_t *JPEG_Set_K_Blocks(uint8_t *pMCUBuffer, uint8_t pKBlocks[16][16], uint32_t ChromaSampling) | |
| { | |
| uint32_t i,j; | |
| if(ChromaSampling == JPEG_420_SUBSAMPLING) | |
| { | |
| /* 4:2:0 4Y + Cb + Cr + K*/ | |
| pMCUBuffer = pMCUBuffer + 384; | |
| /* K block */ | |
| for(i=0;i<16;i+=2) | |
| { | |
| for(j=0;j<16;j+=2) | |
| { | |
| *pMCUBuffer = pKBlocks[i][j]; | |
| pMCUBuffer++; | |
| } | |
| } | |
| } | |
| else if(ChromaSampling == JPEG_422_SUBSAMPLING) | |
| { | |
| /* 4:2:2 2Y horizental + Cb + Cr + K*/ | |
| pMCUBuffer = pMCUBuffer + 256; | |
| /* K block */ | |
| for(i=0;i<8;i++) | |
| { | |
| for(j=0;j<16;j+=2) | |
| { | |
| *pMCUBuffer = pKBlocks[i][j]; | |
| pMCUBuffer++; | |
| } | |
| } | |
| } | |
| else if(ChromaSampling == JPEG_444_SUBSAMPLING) | |
| { | |
| /* 4:4:4 Y + Cb + Cr + K*/ | |
| /* K block */ | |
| pMCUBuffer = pMCUBuffer + 192; | |
| for(i=0;i<8;i++) | |
| { | |
| for(j=0;j<8;j++) | |
| { | |
| *pMCUBuffer = pKBlocks[i][j]; | |
| pMCUBuffer++; | |
| } | |
| } | |
| } | |
| return pMCUBuffer; | |
| } | |
| #endif /* USE_JPEG_ENCODER == 1 */ | |
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |