STMicroelectronics / STM32CubeH7

STM32Cube MCU Full Package for the STM32H7 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
https://www.st.com/en/embedded-software/stm32cubeh7.html
Other
523 stars 309 forks source link

jpeg_utils.c: pure red or pure blue pixel conversion from RGB to YCbCr will result in values too large to hold in a uint8_t buffer. #299

Open jeroen-verfailie opened 3 weeks ago

jeroen-verfailie commented 3 weeks ago

board custom board developed by our company, using the STM32H743. IDE STM32CubeIDE Version: 1.16.1 Build: 22882_20240916_0822 (UTC)

Describe the bug When using the JPEG_ARGB_MCU_YCbCr420_ConvertBlocks function (and possibly also the other convert functions) in jpeg_utils.c to convert an RGB input buffer to YCbCr format, pixels that have a saturated (0xFF) value on either blue or red will result in a Cb or Cr value of 256, which is too large for the uint8_t buffer.

Consequently, this will overflow to 0, resulting in the absence of the color instead of the saturation of it.

As an example, consider the RGB Pixel = (255,0,0).

calculating the crcomp value according to:

crcomp = (int32_t)(*(BLUE_CB_RED_CR_LUT + red)) + (int32_t)(*(GREEN_CR_LUT + green)) + (int32_t)(*(BLUE_CR_LUT + blue)) + 128;

would result in crcomp = 128 + 0 + 0 + 128 = 256

Next,

(*(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = (crcomp);

would cast this to a uint8_t, resulting in: *(pOutAddr + JPEG_ConvertorParams.Cr_MCU_LUT[offset])) = 0 instead of the desired 255.

How To Reproduce IN our project, we take an image with a camera by using the DCMI (works) , debayer & process the image to RGB (works) and eventually encode it to JPEG. We noticed that a test image from the camera had wrong colors for the pure blue and pure red strips.

You can e.g. reproduce this by using the JPEG_EncodingFromFLASH_DMA example but use a pure red RGB or RGBA image instead. The compressed image should have a greenish color instead of the expected red.

root of the problem is very likely in this part of jpeg_utils.c (and equivalent code in other convertors):

        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);

or perhaps the lookup table. I'll let ST decide where it's best to change things.

Let me know if i can provide additional info, test cases or more!

Thanks in advance

Jeroen

KRASTM commented 3 weeks ago

ST Internal Reference: 195507