Skip to main content
DLane.1
Associate II
June 14, 2020
Solved

STM32H7 JPEG encode for grayscale inputs

  • June 14, 2020
  • 6 replies
  • 2388 views

Hello

I am trying to encode an image of (160*120) in grayscale format - i.e a bmp file of 1bpp color depth.

Unfortunately, the encoder would not finish its conversion. and the `HAL_JPEG_EncodeCpltCallback` is not called.

My setup is based on the `JPEG_EncodingUsingFs_DMA` from ST, while this example is designed for 24bits pixel depth, I tried to modify it for my application - with changing the `ReadBmpRgbLines`to read only 1 color:

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, pDataBuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
		pDataBuffer += bytesReadfile;
		*BufferSize += bytesReadfile;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

My encoder values are as follow:

#define JPEG_RGB_FORMAT JPEG_RGB888
 
#define JPEG_CHROMA_SAMPLING JPEG_444_SUBSAMPLING
#define JPEG_COLOR_SPACE JPEG_YCBCR_COLORSPACE\
#define JPEG_IMAGE_QUALITY 100 
#define MAX_INPUT_WIDTH 800 
#define MAX_INPUT_LINES 8 

I have noticed the function that is called to generate a new MCU block is 'stuck` on the same bmp image line.

Can anyone send a hint about this problem? Do I have to set different parameters for the encoder?

Sincerely

Dan

This topic has been closed for replies.
Best answer by sirius506

Oh sorry, you are correct. I didn't noticed that they don't support proper conversion function.

Then, it would be easier to pretend as if you have RGB88 - just repeat the gray scale value three times.

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
 uint8_t workbuffer[200];
 int i;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, workbuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
 for (i = 0; i < Conf.ImageWidth; i++)
 {
		 *pDataBuffer++= workbuffer[i];
		 *pDataBuffer++= workbuffer[i];
		 *pDataBuffer++= workbuffer[i];
 }
		*BufferSize += bytesReadfile * 3;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

6 replies

sirius506
Associate III
June 15, 2020

I believe you should use JPEG_GRAYSCALE_COLORSPACE instead of JPEG_YCBCR_COLORSACE.

#define JPEG_COLOR_SPACE JPEG_GRAYSCALE_COLORSPACE

Regards,

DLane.1
DLane.1Author
Associate II
June 15, 2020

Dear sirius

Thank you for your response.

I tried also the GRAYSCALE_COLORSPACE, which gave in the same result - a non-finished conversion.

BTW I belive the colorspace relates to the convertion output, am I right?

Any other ideas about the convertor parameters?

Dan

sirius506
Associate III
June 15, 2020

JPEG encoder hardware expects MCU format -- where Grayscale MCU and YCBCR MCU formats are different.

In ST's example code, JPEG_GetEncodeColorConvertFunc() handles the difference of color space and returns associated conversion function pointer.

I checked ST's `JPEG_EncodingUsingFs_DMA` example code, and found that you also need to fix BMP_GetInfo() in main.c.

This function expects JPEG_YCBCR_COLORSPACE and  'stucks` at there.

DLane.1
DLane.1Author
Associate II
June 15, 2020

Thank you for your reply

Tthe ` BMP_GetInfo()` can get stuck if the dimentions does not meet the size of (%8 for any color format or %16 for YCMCR format).

My image size (160x120) meets the condition of %8==0 than does not hangs there.

Regarding `JPEG_GetEncodeColorConvertFunc`, the HAL has only functions of convertion of the types: JPEG_ARGB_MCU_Gray_ConvertBlocks. i.e ARGB -> Gray MCU. And I could not find a Gray -> Gray MCU.

I think my only option is to manipulate the input to this MCU generator.

I would really appreciate if you could explain me other method, or reference me to a other MCU building functions.

Thanks

Dan

sirius506
sirius506Best answer
Associate III
June 16, 2020

Oh sorry, you are correct. I didn't noticed that they don't support proper conversion function.

Then, it would be easier to pretend as if you have RGB88 - just repeat the gray scale value three times.

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
 uint8_t workbuffer[200];
 int i;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, workbuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
 for (i = 0; i < Conf.ImageWidth; i++)
 {
		 *pDataBuffer++= workbuffer[i];
		 *pDataBuffer++= workbuffer[i];
		 *pDataBuffer++= workbuffer[i];
 }
		*BufferSize += bytesReadfile * 3;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

DLane.1
DLane.1Author
Associate II
June 16, 2020

That's seems to work

Thanks!