Skip to main content
frackers
Senior
February 19, 2021
Question

F7 hardware jpeg encoding colour failure

  • February 19, 2021
  • 2 replies
  • 2425 views

If I try to encode blocks of colour using the hardware JPEG encode in an F7 from a BMP image (screen memory in this case) they fail if the colour is pure (e.g. all red, all blue) and they come out different shades of green.

By experiment, I have found that extra bits have to be set for the encode to succeed.

Colour Pure code Code that encodes correctly
 red 0xff0000 0xff0202
 green 0x00ff00 0x02ff02
 blue 0x0000ff 0x0202ff

Attached is a jpeg captured by the hardware encoder where the first 3 blocks are 'pure' colours and the other 3 are with the extra bits set.

Is this a limitaion of the encoder or should I be using something other than

#define JPEG_CHROMA_SAMPLING JPEG_420_SUBSAMPLING
#define JPEG_COLOR_SPACE JPEG_YCBCR_COLORSPACE 
#define JPEG_IMAGE_QUALITY 75

in the encoder config.

Thanks

2 replies

Bouraoui Chemli
ST Employee
February 22, 2021

Hi @frackers​ 

It can be related to the JPEG memory requirement...

For more details about Hardware JPEG codec peripheral in STM32F7, you can refer to Application note AN4996.

Also, you may refer to the last STM32CubeF7 firmware package and have a look to the JPEG example under: STM32Cube_FW_F7_Vxx\Projects\STM32F769I_EVAL\Examples\JPEG

Bouraoui

Visitor II
July 29, 2024

you may have problems with converting RGB to YCbCr

if you are unlucky to use jpeg_utils.c from one of these beautiful stm examples, you should be aware that there is a bug in JPEG_InitPreProcColorTables function.

They add 1 for a nicer rounding: ((int32_t) 1 << (16 - 1)) but because of this 1 there is an overflow when RGB color component is close to the maximum: 255 or 254. Just replace ((int32_t) 1 << (16 - 1)) with ((int32_t) 0 << (16 - 1)) or find a better solution.

This one works better, did not test it hard enough though:

 

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) 0 << (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) 0 << (16 - 1))) >> 16 ;
 
 RED_CB_LUT[i] = (((-((int32_t) ((0.1687 ) * (1L << 16)))) * i) + ((int32_t) 0 << (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) 0 << (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) 0 << (16 - 1))) >> 16 ;
 }
}