cancel
Showing results for 
Search instead for 
Did you mean: 

F7 hardware jpeg encoding colour failure

frackers
Senior

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 2
Bouraoui Chemli
ST Employee

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

gamnocoder
Associate

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